單一命令採用兩個字串來提取它們之間的字串,例如“tr”(不含表達式)

單一命令採用兩個字串來提取它們之間的字串,例如“tr”(不含表達式)

這裡一種使用 sed 取得一行中其他兩個字串之間的文字的方法,例如:

sed 's/.*starting_text\(.*\)ending_text.*/\1/'

但我想要一個簡單的命令(例如tr,但用於字串提取),只需兩個字串,並會修剪第一個字串之前或第二個字串之後的所有內容,例如

grep something some_file | between message\"\:\" " with"

並會處理轉義字元。

答案1

如果分隔符號可能每行出現多次,您可以使用 perl 代替,如下所示:

between() {
  perl -Tlne 'BEGIN{$b=shift;$e=shift}
             print for /\Q$b\E(.*?)\Q$e\E/g' "$@"
}

然後例如:

$ echo "[b]test[e] foo [b]bar[e]" | between '[b]' '[e]'
test
bar

您也可以將其用作:

between BEG END file1 file2...

答案2

通常在 sed 中執行此操作需要在用於查找我找到的子字串的正則表達式中轉義字符這裡(註:更多信息這裡如果您遇到問題)。

然後,我找到如何透過管道傳輸到函數中這裡

將所有這些放在一起到一個我可以在 my 中使用的函數中.bashrc,看起來像(雖然我不必設置 a 和 b 變量,但它更容易閱讀):

between(){
  a=$(printf '%s\n' "$1"|sed 's![\*.^$/[]!\\&!g')
  b=$(printf '%s\n' "$2"|sed 's![\*.^$/[]!\\&!g')
  sed "s/.*$a\(.*\)$b.*/\1/"
}

正如約瑟夫R.所提到的,這個答案展示如何使用 grep -oP 執行類似操作。為了轉義 Perl 相容的正規表示式,我發現,所以也許下面的方法也可以工作:

between(){
  a=$(printf '%s\n' "$1"|sed 's![]\*.^+?(){|$[]!\\&!g')
  b=$(printf '%s\n' "$2"|sed 's![]\*.^+?(){|$[]!\\&!g')
  grep -oP "(?=$a).*?(?=$b)"
}

相關內容