以下sed命令:
sed -E -e 's#µ(bar)>([^|¢]+)\|([^µ|]+)¢#:\1:`\3 <\2>`#g':\1:`\3 <\2>` 
µ和¢之间的内容,
\1、\2、\3),其中>和|作为分隔符,H 213H 114并返回例如:
$ sed -E -e 's#µ(bar)>([^|¢]+)\|([^µ|]+)¢#:\1:`\3 <\2>`#g' <<< "µbar>foo|baz¢"
:bar:`baz <foo>`
$ sed -E -e 's#µ(bar)>([^|¢]+)\|([^µ|]+)¢#:\1:`\3 <\2>`#g' <<< "µbar>foo|foo¢"
:bar:`foo <foo>`现在,我想只返回:\1:`\2`,在\3和\2是相同的情况下,以便在第二个示例中得到:bar:`foo`。
如何使用sed (可能在另一个工具的帮助下)实现这一结果?
编辑1
更广泛地说,我的实际用例涉及备选方案,例如以下选项(只有第一个用例需要以反向引用为条件):
sed -E -e 's#µ(bar1|bar2|bar3)>([^|¢]+)\|([^µ|]+)¢#:\1:`\3 <\2>`#g ; s#µ(bar1|bar2|bar3)>([^|¢µ]+)¢#:\1:`\2`#g'@anubhava对我的第一个问题的第一个回答是基于awk的,它的语法对我来说非常深奥:)
编辑2
在我最初的问题中,第一个组不应该匹配([^...])分隔符(µ、|和µ),以便处理同一行上多次出现的模式。备注:图案可能被文字包围,特别是可能不在行首。
此外,我还必须处理没有|分隔符的情况(我的编辑1的第二个sed命令),例如µbar3>foo¢应该返回:bar3:`foo`
因此,一个更真实的测试文件应该是:
Bla bla bla µbar1>foo|baz¢ bla bla bla µbar2>foo|foo¢ bla bla bla.
Bla bla bla µbar3>foo¢ bla bla bla.预期产出如下:
Bla bla bla :bar1:`baz <foo>` bla bla bla :bar2:`foo` bla bla bla.
Bla bla bla :bar3:`foo` bla bla bla.发布于 2020-12-09 03:17:52
如果Perl是您的选择,请您尝试以下方法:
perl -pe 's#μ(.+?)>(.+?)(?:\|(.+?))?¢#
    sprintf(":%s:`%s`", $1, ($3 eq "" or $2 eq $3) ? $2 : "$3 <$2>") #ge' < input.txtinput.txt
μbar>foo|baz¢
μbar>foo|foo¢
μbar>foo¢
Bla bla bla μbar1>foo|baz¢ bla bla bla μbar2>foo|foo¢ bla bla bla.
Bla bla bla μbar3>foo¢ bla bla bla.输出:
:bar:`baz <foo>`
:bar:`foo`
:bar:`foo`
Bla bla bla :bar1:`baz <foo>` bla bla bla :bar2:`foo` bla bla bla.
Bla bla bla :bar3:`foo` bla bla bla.delimiters.
-pe选项告诉Perl逐行处理输入文件,然后像sed -e那样打印每一行。regex .+?与子字符串匹配尽可能短,如果输入行包含多个overrun regex (?:pattern)类似于分组(pattern),但它不创建用于反向引用的捕获组,则不必关心overrun。(这意味着regex最多生成从$1到$3的反折射,而不是对regex的$1 g选项启用全局(多个)匹配。e选项允许替换不仅是字符串,而且是perl表达式。这是一个强大的特性,可以使替换变得非常灵活(希望readable).($3 eq "" or $2 eq $3) ? $2 : "$3 <$2>"看起来很模糊,但它只是一个条件运算符,意思是如果$3为空或$2和$3相同,则打印$2,否则打印"$3 <$2>“。)
发布于 2020-12-08 16:44:54
现在,我想要的是只返回
和
\2相同的情况下的:\1:`\2`。
在这里使用awk更容易,如下所示:
cat file
µbar>foo|baz¢
µbar>foo|foo¢awk命令:
awk -F '[|>]+' '$1 ~ /^µ(bar1|bar2|bar3)$/ {
   sub(/¢$/, "", $3)
   print ":" substr($1, 2) ":`" ($2 != $3 ? $2 " " : "") "<" $3 ">`"
}' file
:bar:`foo <baz>`
:bar:`<foo>`由于问题在这里发布后已被大量修改,所以需要一个gnu-awk来获得预期的输出:
awk '{
   while (match($0, /µ(bar1|bar2|bar3)>([^|¢]+)(\|([^µ|]+))?¢/, m)) { 
      printf "%s", substr($0, 1, RSTART-1) ":" m[1] ":`" (m[4] != "" ? m[4] (m[2] != m[4] ? " <" m[2] ">" : "") : m[2]) "`"
      $0 = substr($0, RSTART+RLENGTH)
   }
   print ""
}' file
Bla bla bla :bar1:`baz <foo>` bla bla bla :bar2:`foo`
Bla bla bla :bar3:`foo`https://stackoverflow.com/questions/65202868
复制相似问题