Sed

如何使用相同數量的重複字元獲取兩個字元串之間的內容?

  • March 9, 2022

本質上,我試圖獲取兩個字元串之間的內容,但是使用相同的字元重複 N 次,如下所示:

===
This is a test
===

====
Another test
====

==
Last test
==

當然,以上只是一個例子。這是我嘗試過的和他們的結果:

sed -u '/==/!d;s//&\n/;s/.*\n//;:a;/==/bb;$!{n;ba};:b;s//\n&/;P;D' testfile

=
This is a test

=




Another test






Last test

如果我只使用上述之一testfile


Last test

這將給出想要的結果(儘管添加了太多的換行符,但這對於這個例子來說很好)。

僅當存在這些重複字元的單個實例或者它是包含內容的一對唯一字元串時,上述方法才有效…

如何使用相同數量的重複字元獲取兩個字元串之間的內容?我更喜歡使用grepsedawk為此。

tl;博士

$ sed '/^==*$/,//{//!p};d' testfile
This is a test
Another test
Last test

乍一看,一個簡單的範圍可以列印所有對(不需要循環):

$ sed -n '/^=/,//p' testfile
===
This is a test
===
====
Another test
====
==
Last test
==

=這會列印以開頭的行和下一個重複的正則表達式 ( //)之間的每一行。

這可以改進為包含=:的行/^==*$/

並刪除所有標記:

$ sed -n '/^==*$/,//H;${x;s/\n==*//g;s/^\n//;p}' testfile
This is a test
Another test
Last test

或者,以更短的形式:

$ sed -n '/^==*$/,//{//d;p}' testfile
This is a test
Another test
Last test

=要匹配將正則表達式更改為的確切數量:

$ sed -n '/^==$/,//{//d;p}' testfile
Last test

並且,為了避免該-n選項:

$ sed '/^==$/,//{//!p};d' testfile
Last test

在 awk 中可以這樣做:

$ awk 'p==0 && /^==*$/ {p=1;next}
      p==1 && /^==*$/ {p=0}
      p          
     ' testfile

This is a test
Another test
Last test

或者,以不太明確的形式:

awk ' /^==*$/ { p = !p ; next}
     p
   ' testfile

我們使用awk實用程序來使用觸發器邏輯從開啟狀態切換到關閉狀態,如下所示:

$ awk -v str="==" '
     $0""==str{f=!f;next};f
' testfile
Last test

使用 Posixly sed結構,我們可以實現觸發器邏輯:

sed -ne '
 /^==$/{
   x;        # access state info from hold
   s/^$/0/;  # initialize state
   y/01/10/; # toggle state
   x;        # save state in hold
   d;        # next
 }
 G;/\n1/P
' testfile

在擴展模式下使用 GNU 版本的流編輯器sed-E

$ sed -Ee '
   $!N; /^(\S)\1+\n/!D
   :loop
       $d;N
       s/^(.*)\n(.*)\n\1$/\2/;t
   bloop
' testfile
This is a test
Another test
Last test

筆記:-

  • 通過命令保持兩行模式空間N
  • 繼續拒絕行,直到我們遇到黃金線(=> 模式空間的第一部分僅包含一種類型的非空白字元)
  • 一旦找到這樣的一條線,我們就會循環,直到我們在路上遇到至少兩條線的精確複製品。我們已經找到了第一組。
  • 這個過程一直重複,直到我們到達 eof。

使用perl中的觸發器運算符...,我們可以如下所示:

perl -lne 'print if 
/^(\S)\1+$(?{$a=$_})/ ... $_ eq $a and $_ ne $a;
' testfile

對於固定的預定字元串,搜尋更簡單,因為這樣我們就不必製作正則表達式,而字元串相等測試就足夠了:

$ perl -nlse 'print if
   $_ eq $a ... $_ eq $a and $_ ne $a;
' -- -a=== testfile

$ sed -Ee '
   /^==$/!d
   $!N
   :a
       $d;N
       s/^(.*)\n(.*)\n\1$/\2/;t
   ba
' testfile

引用自:https://unix.stackexchange.com/questions/648741