提取两个常量字符串之间的 WORD

Extract WORD between two constant strings

我有以下字符串

xml_srx_name="<name>SRX-NAME</name>"

我正在尝试打印 > 和 < 之间的文本 所以它会打印 SRX-NAME

我真的很接近,但这就是我得到的:>SRX-NAME< 这是我用这个命令能够实现的:

$ cat $xml_srx_name | awk '/SRX-NAME/ {print }' | grep -oPz "(?s)>.*?<" | tr '[=11=]' '\n'

Output:
>SRX-NAME<
input="test<hello>text"

rightpart=${input#*<}   # remove prefix up to "<" (included)
output=${rightpart%>*}  # remove suffix from ">" (included)

echo $output

在 bash 中使用 extglob,您可以一步完成:

shopt -s extglob
input='test<hello>heythere'
echo "${input//@(*<|>*)/}"

此处@(<|>) 匹配从开始到 < 字符的子字符串或从 > 到结束的子字符串。使用 // 我们将所有此类实例替换为空字符串。

你可以试试

  1. 最后加| tr -d '<>'
  2. 使用cat … |grep -o SRX-NAME
  3. 使用cat … |cut -d \> -f 2 | cut -d \< -f 1

如果您最终得到一个使用 catawkgreptr 的复合命令,您可能有一个很好的 anti-pattern 示例. awk一个人就够了:

$ xml_srx_name="<name>SRX-NAME</name>"
$ awk -F'<|>' '/SRX-NAME/ {print }' <<< "$xml_srx_name"
SRX-NAME

sed:

$ sed '/SRX-NAME/s/.*>\(.*\)<.*//' <<< "$xml_srx_name"
SRX-NAME

您可以使用具有零长度断言的 GNU grep,如下所示让 file.txt 内容为

xml_srx_name="<name>SRX-NAME</name>"

然后

grep -Po "(?<=\>).*(?=\<)" file.txt

输出

SRX-NAME

解释:在>之后和<.

之前找到0个或多个任意字符

(在 GNU grep 3.4 中测试)

您也可以仅使用 grep -oP 使用 perl 兼容的正则表达式:

<(name>)\K[^<]+(?=</)

或者写出完整的模式:

<name>\K[^<]+(?=</name>)

说明

  • <字面匹配
  • (name>)\K 在组 1
  • 中捕获 name>
  • [^<]+ 匹配 <
  • 以外的 1+ 个字符
  • (?=</) 正面前瞻,向右断言

示例

xml_srx_name="<name>SRX-NAME</name>"
grep -oP "<(name>)\K[^<]+(?=</)" <<< "$xml_srx_name"

输出

SRX-NAME

bash demo


或将 sed 与捕获组一起使用:

xml_srx_name="<name>SRX-NAME</name>"

sed 's/.*<name>\([^<]\+\)<\/name>.*//' <<< "$xml_srx_name"

sed demo

在每个 Unix 机器上的任何 shell 中使用任何 sed 或 awk:

$ xml_srx_name="<name>SRX-NAME</name>"

$ echo "$xml_srx_name" | awk -F'[<>]' '{print }'
SRX-NAME

$ echo "$xml_srx_name" | sed 's/.*>\(.*\)<.*//'
SRX-NAME

任何包含 SRX-NAME 的脚本都是毫无意义的,因为这意味着您已经知道要查找的字符串,因此可以只执行 echo 'SRX-NAME'