Bash

在第一個匹配的括號之間列印內容

  • January 9, 2021

輸入範例:

START{
   some text

   {
     more text}
almost there
}
nothing important{
...

期望的輸出:

START{
   some text

   {
     more text}
almost there
}

第一個開括號可以在不同的位置:

START{...
START {...
START
{...

開始還可以包含特殊字元,例如:*

我想列印出所有內容,包括從 START 開始的所有內容以及第一次匹配之間的所有內容{}(在 bash 中)。我正在考慮有一個計數器,它在找到{時增加,在找到時減少}。當結果為零時,它會停止列印(大括號總是匹配的)。

pcregrep

start_word='START'
pcregrep -Mo "(?s)\Q$start_word\E\h*(\{(?:[^{}]++|(?1))*+\})" < your-file

使用zsh內置函式:

set -o rematchpcre
start_word='START'
[[ $(<your-file) =~ "(?s)\Q$start_word\E\h*(\{(?:[^{}]++|(?1))*+\})" ]] &&
 print -r -- $MATCH

那些使用 PCRE 的遞歸正則表達式功能,(?1)上面呼叫了第一(...)對中的正則表達式。

如果你既沒有pcregrep也沒有zsh,你總是可以求助於真實的東西(PCRE中perl的):P

perl -l -0777 -sne '
   print $& if /\Q$start_word\E\h*(\{(?:[^{}]++|(?1))*+\})/s
 ' -- -start_word='START' < your-file

(請注意,除perl一個之外的所有內容都假定$start_word不包含\E)。

一種簡單的蠻力方法,可以在所有 Unix 機器上的任何 shell 中的任何 awk 中工作:

$ cat tst.awk
s=index($0,"START") { $0=substr($0,s); f=1 }
f { rec = rec $0 RS }
END {
   len = length(rec)
   for (i=1; i<=len; i++) {
       char = substr(rec,i,1)
       if ( char == "{" ) {
           ++cnt
       }
       else if ( char == "}" ) {
           if ( --cnt == 0 ) {
               print substr(rec,1,i)
               exit
           }
       }
   }
}
$ awk -f tst.awk file
START{
   some text

   {
     more text}
almost there
}

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