输入:
<e1 name="file1" id="id1" anotherId="id2">
期望的输出:
file1
我可以用这个得到我需要的东西:
echo '<e1 name="file1" id="id1" anotherId="id2">' | sed 's/\(.*name="\)\(.*\)\(".*\)/\2/' | sed 's/".*//'
输出:file1
我想改进命令集,并在可能的情况下删除 sed 的最后一个管道。如果我删除 sed 的最后一个管道,我将无法得到我想要的:
echo '<e1 name="file1" id="id1" anotherId="id2">' | sed 's/\(.*name="\)\(.*\)\(".*\)/\2/'
输出:
file1" id="id1" anotherId="id2
正如您所看到的,sed 选取了最后一个引号,而不是 file1 之后的第一个引号。
有人可以帮助改进这个命令吗?
答案1
echo '<e1 name="file1" id="id1" anotherId="id2">' |
sed -n 's/.*name="\([^"]*\)".*/\1/p'
或者使用 GNU(grep
如果使用 PCRE 支持构建):
echo '<e1 name="file1" id="id1" anotherId="id2">' |
grep -Po 'name="\K[^"]*'
答案2
sed
您可以使用此版本稍微简化一下:
$ echo '<e1 name="file1" id="id1" anotherId="id2">' | \
sed 's/.*name="\(.*\)" id.*/\1/'
您不需要用括号包裹所有内容,只需要保存您感兴趣的内容以供以后使用,这样您就可以删除。
grep
您还可以grep
使用 Perl 的正则表达式引擎(PCRE)的能力:
$ echo '<e1 name="file1" id="id1" anotherId="id2">' | \
grep -Po '(?<=name=")(\w+)(?=")'
这利用了 PCRE 的向前看和向后看的能力。该表示法查找字符序列,例如"name="
前我们正在寻找什么。这个位正在这样做:
(?<=name=")
然后它会查找一系列单词字符,这就是我们实际要查找的:
(\w+)
进行前瞻的最后一点是:
(?=")
它正在寻找引号 ( "
)后我们正在寻找什么。
awk
$ echo '<e1 name="file1" id="id1" anotherId="id2">' | \
awk '{gsub("\"","");split($2,a,"="); print a[2]}'
此变体将双引号 (``"``) 字符串化,进行全局替换:
gsub("\"","")
剩余的字符串将是这样的:
<e1 name=file1 id=id1 anotherId=id2>
因此,我们可以awk
像平常一样将其拆分,第二列将是我们感兴趣的部分。那将$2
是awk
。因此我们可以采用该变量,然后将其拆分为等号 ( =
)。
split($2,a,"=");
这将拆分$2
,并将结果存储在数组 中a
。之后我们可以打印数组中的第二个元素,这是等号右侧的所有内容$2
。
file1