Wie fügt man vor einem Muster einen Backslash und eine neue Zeile ein?

Wie fügt man vor einem Muster einen Backslash und eine neue Zeile ein?

ich wollte \n in einer Variablen erfassen (angenommen a) und $a vor dem Suchmuster in einer Datei (abc.txt) ersetzen.

kann mir jemand eine Lösung vorschlagen?

> cat abc.txt
hi how are you how is your health
> echo $a
\

erwartete Ausgabe ( Suchmuster - how)

hi \
how are you \
how is your health

Antwort1

In einer Bourne-ähnlichen oder rc-ähnlichen Shell

a='
' perl -pe 's/pattern/$ENV{a}$&/g' < abc.txt

würde eine aUmgebungsvariable an übergeben, die perlein Zeilenumbruchzeichen enthält, und perlwürde den Inhalt dieser Variablen vor jedem Vorkommen von patternim Inhalt von einfügen abc.txt.

Um in Bourne-ähnlichen Shells ein beliebiges xanderes Zeichen als eine Variable zuzuweisen , können Sie Folgendes verwenden:'

a='x'

Also für den Backslash:

a='\'

Für eine neue Zeile:

a='
'

Für Steuerzeichen wie Newline wäre das allerdings noch schlimmer, beispielsweise für Backspace oder Carriage-Return, da der Code dadurch allerdings unleserlicher wird.

ksh93 führte eine neue $'...'Form von Anführungszeichen ein, um diese Zeichen in einer Escape-Form anzugeben. Andere Shells wie bash, zshoder mkshFreeBSD haben es seitdem shkopiert und erweitert (wie die $'\uXXXX'von hinzugefügte Form ).zsh

In diesen Shells können Sie Folgendes verwenden:

a=$'\n' a=$'\b' a=$'\r' a=$'\\' a=$'\''

So weisen Sie ein Zeilenumbruch-, Rücktaste-, Wagenrücklauf-, Backslash- oder einfaches Anführungszeichen zu.

Dieser Anführungszeichenoperator ist noch nicht Standard, Sie können ihn also nicht in portablen shSkripten verwenden. Eine Standardalternative ist:

a=$(printf '\b')

für Backspace zum Beispiel, aber das funktioniert nicht für Newline, da die Befehlssubstitution ( $(cmd)) nachfolgende Newline-Zeichen aus der Ausgabe von entfernt cmd. Man muss auf Hacks wie diese zurückgreifen:

nl=$(printf '\n.'); nl=${nl%.}

(das heißt, ein hinzufügen .und anschließend entfernen), um es beizubehalten.

Beachten Sie, dass perldiese \nNotationen auch in seinem Code verstanden werden, sodass Sie Folgendes tun können:

perl -pe 's/pattern/\n$&/g' < abc.txt

Die GNU-Implementierung von sed(und heutzutage auch einige andere) unterstützt dies ebenfalls:

sed 's/pattern/\n&/g' < abc.txt

aber das ist nicht Standard. Normalerweise muss ein Zeilenumbruch im Ersetzungsteil des sBefehls mit einem Backslash gefolgt von einem tatsächlichen Zeilenumbruch ausgedrückt werden, also wäre das:sed

backslash='\' newline='
'
sed "s/pattern/$backslash$newline&/g" < abc.txt

Oder ohne die Variablen:

sed 's/pattern/\
&/g' < abc.txt

Wenn Sie also sowohl einen Backslash als auch eine neue Zeile vor einfügen möchten pattern, benötigen Sie:

sed 's/pattern/\\\
&/g' < abc.txt

Insgesamt 3 Backslashs, zwei für einen wörtlichen Backslash und einer für den Zeilenumbruch. Oder mit perl:

perl -pe 's/pattern/\\\n$&/g' < abc.txt

Oder mit Ihrer aVariable:

a='\
' perl -pe 's/pattern/$ENV{a}$&/g' < abc.txt

Antwort2

Sie können auch eigene Bash-Befehle verwenden mit:

cat abc.txt | sed -e 's/how/\nhow/g' |  while read line; do echo "$line \\"; done

verwandte Informationen