改进 sed 命令以替换字符的第一个实例和所有后续字符?

改进 sed 命令以替换字符的第一个实例和所有后续字符?

输入:

<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像平常一样将其拆分,第二列将是我们感兴趣的部分。那将$2awk。因此我们可以采用该变量,然后将其拆分为等号 ( =)。

split($2,a,"=");

这将拆分$2,并将结果存储在数组 中a。之后我们可以打印数组中的第二个元素,这是等号右侧的所有内容$2

file1

相关内容