将字符串修剪到 Bash 中的某些字符

Trimming string up to certain characters in Bash

我正在尝试制作一个 bash 脚本,它将告诉我 Linux 内核的最新稳定版本。

问题是,虽然我可以删除某些字符之后的所有内容,但我似乎无法删除某些字符之前的所有内容。

#!/bin/bash

wget=$(wget --output-document - --quiet www.kernel.org | \grep -A 1 "latest_link")

wget=${wget##.tar.xz\">}

wget=${wget%</a>}

echo "${wget}"

以某种方式输出 "ignores" wget=${wget##.tar.xz\">} 行。

您正在尝试从字符串的开头删除模式 .tar.xz\"> 的最长匹配项,但您的字符串不是以 .tar.xz 开头,因此没有匹配项。

你必须使用

wget=${wget##*.tar.xz\">}

然后,因为你在脚本中而不是交互式 shell,所以不需要转义 \grep(大概是为了防止使用别名),作为别名在非交互式 shell 中被禁用。

并且,如前所述,将变量命名为与现有命令相同的名称(经常发现:test)必然会导致混淆。

如果您想使用专为处理 HTML 而设计的命令行工具,您可以查看 W3C HTML-XML-utils (Ubuntu: apt install html-xml-utils)。使用它们,您可以获得您想要的信息,如下所示:

$ curl -sL www.kernel.org | hxselect 'td#latest_link' | hxextract a -
4.10.8

或者,详细地说:

curl -sL www.kernel.org |     # Fetch page
hxselect 'td#latest_link' |   # Select td element with ID "latest_link"
hxextract a -                 # Extract link text ("-" for standard input)

每当我需要在 bash 中提取一个子字符串时,我总是看看我是否可以通过几个 cut(1) 命令来暴力破解它。在您的情况下,以下内容似乎有效:

wget=$(wget --output-document - --quiet www.kernel.org | \grep -A 1 "latest_link")
echo $wget | cut -d'>' -f3 | cut -d'<' -f1

我确信有更优雅的方法,但它的语法简单,我永远不会忘记。请注意,如果 'wget' 将来获得额外的“>”或“<”字符,它将中断。

不推荐使用shell工具grep、awk、sed等解析HTML个文件。

但是,如果您想要一个快速的衬里,那么这个 awk 应该可以胜任:

get --output-document - --quiet www.kernel.org |
awk '/"latest_link"/ { getline; n=split([=10=], a, /[<>]/); print a[n-2] }'

4.10.8

sed方法:

wget --output-document - --quiet www.kernel.org | \
  sed -n '/latest_link/{n;s/^.*">//;s/<.*//p}'

输出:

4.10.8