Einzelner Befehl, der zwei Zeichenfolgen verwendet, um die Zeichenfolge dazwischen zu extrahieren, wie „tr“ (ohne Ausdrücke)

Einzelner Befehl, der zwei Zeichenfolgen verwendet, um die Zeichenfolge dazwischen zu extrahieren, wie „tr“ (ohne Ausdrücke)

GesehenHiereine Möglichkeit, mit sed Text zwischen zwei anderen Zeichenfolgen in einer Zeile einzufügen, etwa:

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

aber ich hätte gerne einen einfachen Befehl (wie tr, aber für die String-Extraktion), der nur zwei Strings nimmt und alles vor dem ersten String oder nach dem zweiten String trimmt, zB

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

und würde das Escapen von Zeichen handhaben.

Antwort1

Wenn die Trennzeichen mehrmals pro Zeile vorkommen können, können Sie stattdessen Perl wie folgt verwenden:

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

Und dann zum Beispiel:

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

Sie können es auch verwenden als:

between BEG END file1 file2...

Antwort2

Wenn man das in sed allgemein machen würde, müsste man Zeichen im regulären Ausdruck maskieren, der zum Suchen der Teilzeichenfolge verwendet wird, die ich gefunden habeHier(Hinweis: Weitere InformationenHierfalls Probleme auftreten).

Dann habe ich herausgefunden, wie man in eine Funktion hineinleitetHier.

Wenn ich das alles in einer Funktion zusammenfasse, die ich in meinem verwenden kann .bashrc, sieht das so aus (obwohl ich die Variablen a und b nicht festlegen muss, aber es ist leichter zu lesen):

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

wie Joseph R. erwähnte,diese Antwortzeigt, wie man mit grep -oP ähnliches erreichen kann. Um Perl-kompatiblen regulären Ausdrücken zu entgehen, habe ichDas, also würde vielleicht auch Folgendes funktionieren:

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

verwandte Informationen