试图用另一种模式替换一种模式

Trying to replace a pattern with another one

这是我在这个网站上的第一个问题。(很高兴我发现了这个社区)

我正在尝试替换文件(多行)中看起来像这样的特定模式:

Bla bla bla bla |SMTH AWESOME INSIDE >>> LOL| bla bla bla | let's do it again >>> AWESOME |

转换成如下格式

Bla bla bla bla ( LOL | SMTH AWESOME INSIDE ) bla bla bla ( AWESOME | let's do it again )

我尝试通过使用逐字解析行的代码来执行此操作,如果它找到“|”字符开始创建包含第一个单词的字符串,然后在找到 >>> 字符后开始创建第二个字符串,直到找到“|”最后一个字符,但没有用。

之后我也尝试使用 AWK(但由于我是 linux 的新手,所以我也失败了。

awk -F 'BEGIN { FS=OFS="|" } { sub(/.*<<</,"", ); }1'  }'    

然后用 sed 解析输出(从两个字符串中删除 ) 和 ( 字符。但它没有用。

感谢阅读。

Perl 的正则表达式有一个 "non-greedy" awk 没有的匹配特性:

perl -pe '
    s/ \|       # the first delimiter
       (.*?)    # capture up to ...
       >>>      # the middle delimiter
       (.*?)    # capture up to ...
       \|       # the last delimiter
    /( | )/gx
' file
Bla bla bla bla ( LOL | SMTH AWESOME INSIDE ) bla bla bla ( AWESOME  |  let's do it again )

看起来这只是每行中的一个简单替换,所以您只需要 sed:

$ sed 's/| *\([^|]*\) >>> \([^|]*\) *|/(  |  )/g' file
Bla bla bla bla ( LOL | SMTH AWESOME INSIDE ) bla bla bla ( AWESOME  | let's do it again )

您可以在 GNU awk 中使用 gensub() 或使用 match() 和 substr() 的其他 awk 执行相同的操作。

sed 中使用扩展正则表达式:

sed -r 's/\|([^|]+)[[:space:]]*>>>[[:space:]]*([^|]+)\|/(  |  )/g' File

逻辑:

我们寻找以 | 开头的模式,然后是一系列非 | 字符,然后是 >>>,然后是一系列非 |字符再次。查看使用 () 完成的分组。然后我们根据需要替换这些模式。 ( | ) 是替换模式,其中 \1 和 \2 分别是第一组和第二组。

使用 sed 中的基本正则表达式:

sed 's/|\([^|]*\)[[:space:]]*>>>[[:space:]]*\([^|]*\)|/(  |  )/g' File

让我们试试 :

awk 'NR%2{ printf("%s", [=10=]) } NR%2==0{ printf("( %s %s",$NF,RS); gsub(/>>>.*$/,")"); printf("%s",[=10=]) }' RS='|' file
Bla bla bla bla ( LOL | SMTH AWESOME INSIDE ) bla bla bla ( AWESOME | let's do it again )

RS定义|为记录分隔符。因此,当输入记录编号 (NR) 不是 2 的模数 (NR%2 return 1) 时,则打印该记录本身。如果 NR 是 2 的模块(NR%2==0 表示如果记录是 2 的模块),则打印单个左括号,然后打印最后一个字段并打印记录分隔符(printf("( %s %s",$NF,RS)) , 然后用右括号替换 >>>.*$ 并打印记录的其余部分 (gsub(/>>>.*$/,")"); printf("%s",[=18=]))