Durch Leerzeichen begrenzen, aber Backslash-Leerzeichen ignorieren

8
5678 []
testing,\ group []
[testing []
ip\ 5.6.7.8 []
launch-wizard-1 0.0.0.0/0
456dlkjfa []
1.2.3.4 []
test 1.2.3.4/32 4.3.2.0/23 4.3.2.0/23
default 4.3.2.0/23 4.3.2.0/23
launch-wizard-2 0.0.0.0/0
launch-wizard-3 0.0.0.0/0
2.3.4.5/32 []

Ich möchte die erste Spalte der obigen Spalte erhalten, aber der Haken ist, dass ich \ (Backslash Space) als Teil der Spalte behandeln muss, also awk '{print $1}'sollte ich geben

5678
testing,\ group
[testing
ip\ 5.6.7.8
launch-wizard-1
456dlkjfa
1.2.3.4
test
default
launch-wizard-2
launch-wizard-3
2.3.4.5/32
GypsyCosmonaut
quelle
Wird \ immer als Fluchtzeichen behandelt oder ist es nur etwas \ Besonderes? Ist zum Beispiel a\\ bein Feld oder zwei?
Gregory Nisbet
@GregoryNisbet Ich habe \ eingegeben, ist für Escape-Zeichen, nicht die realen Daten
GypsyCosmonaut
1
Wenn Ihre Daten einen echten Backslash enthalten würden, wie würden sie dargestellt?
Gregory Nisbet
@ GregoryNisbet Gute Frage. Da ich nur [[:space:]]durch ersetzt habe \[[:space:]], sind die Originaldaten an ihrer Stelle unberührt geblieben. Nachdem sie die Originaldaten in der ersten Spalte nur Leerzeichen getrennt und nicht \[[:space:]], würde ich ersetzen \[[:space:]]mit [[:space:]]und ich würde wieder mit Originaldaten bleiben die hat \.
GypsyCosmonaut

Antworten:

9

Mit gnu awk ( gawk) können Sie einige Aussagen mit der Länge Null verwenden, wie \<oder \>:

$ echo 'a\ b c' | gawk 'BEGIN{FS="\\> +"} {print $1}'
a\ b

aber leider nicht die ausgewachsen diejenigen aus perloder pcre(zB. (?<!\\), (?<=\w)usw.):

$ echo 'a\ b, c' | perl -nle '@a=split /(?<!\\)\s+/, $_; print $a[0]'
a\ b,
Mosvy
quelle
5

Sie könnten \ space durch etwas anderes ersetzen und danach wieder zurückkehren.

sed 's/\\ /\\x20/g' data_file | awk '{ print $1; }' | sed 's/\\x20/\\ /g'
pLumo
quelle
Nur mit sed: sed 's / \\ / \\ x20 / g; s /. * //; s / \\ x20 / \\ / g' data_file
ctac_
Oder, awk, mit dem Standardwert der SUBSEP-Variablen \034:awk '{gsub(/\\ /,SUBSEP,$0); val=$1; gsub(SUBSEP,"\\ ",val); print val}' file
Glenn Jackman
5

Mit GNU grepoder kompatibel:

grep -Po '^(\\.|\S)*'

Oder mit ERE:

grep -Eo '^(\\.|[^\[:space:]])*'

Das wird \als Anführungszeichen behandelt , für Leerzeichen als Trennzeichen, aber auch für sich. Das heißt, bei der foo\\ barEingabe wird zurückgegeben foo\\.

Stéphane Chazelas
quelle
4

Mit nur sed:

sed -r 's/^((([^\]*\\ ){1,})?[^ ]*).*/\1/' infile

Oder kürzer:

sed -r 's/^(([^\]*\\ )*[^ ]*).*/\1/' infile

Dies (([^\]*\\ ){1,})?[^ ]*passt zu:

  • [^\]*\\: Alles, was kein Schrägstrich ist, der mit einem Schrägstrich gefolgt von einem Leerzeichen endet (beachten Sie, dass die \innere Zeichenklasse nicht maskiert werden muss, sondern die äußere).
  • ([^\]*\\ ){1,}: oben mit einem oder mehreren Vorkommen übereinstimmen.
  • (([^\]*\\ ){1,})?: Dies ist optional bei Verwendung (...)?; wir könnten ([^\]*\\ ){0,}stattdessen auch oder verwenden ([^\]*\\ )*.
  • ((([^\]*\\ ){1,})?[^ ]*): Übereinstimmungen darüber, die optional sind, gefolgt von allem, was kein Leerzeichen ist, und als Gruppenübereinstimmung mit \1als Hintergrundreferenz.
  • ((([^\]*\\ ){1,})?[^ ]*).*: passt oben (...)und alles andere .*.

Dann wird das Ersatzteil einfach gedruckt, \1welches die Ausgabe ist:

5678
testing,\ group
[testing
ip\ 5.6.7.8
launch-wizard-1
456dlkjfa
1.2.3.4
test
default
launch-wizard-2
launch-wizard-3
2.3.4.5/32
αғsнιη
quelle