Entfernen Sie ein oder mehrere Felder, die durch ein "-" am Zeilenende getrennt sind

8

Ich werde die Daten googleapis.txt analysieren

bucket,abc-def-ghi-45gjd4-wwxis
bucket,dde-wwq-ooi-66ciow-po22q
instance,jkl-mno-1-zzz-68dkakw-oo9w8
disk,pqr-stu-10-kuy-l2oxapw-rp4lt

Ich erwarte das Ergebnis wie folgt

bucket,abc-def-ghi
bucket,dde-wwq-ooi
instance,jkl-mno-1-zzz
disk,pqr-stu-10-kuy

Ich denke, dass ich mich ändern muss -, um ein Leerzeichen zu sein, und dann diesen Befehl ausführen muss

cat googleapis.txt | awk '{$NF="";sub(/[ \t]+$/,"")}1' | awk '{$NF="";sub(/[ \t]+$/,"")}1'

Ich habe das von diesem https://stackoverflow.com/a/27794421/8162936 bekommen. Nach dem Parsen werde ich den Raum ändern , um ein Hypen -zurück zu sein.

Kennt jemand die Best Practice oder den Einzeiler-Shell-Befehl zum Parsen? Vielen Dank an alle

Nicky Puff
quelle

Antworten:

10

mit seddir kannst du machen:

sed -E 's/(-[^-]*){2}$//' infile

Passen Sie ein Muster wie -anythingzweimal (...){2}am Ende $jeder Zeile an und entfernen Sie es.

αғsнιη
quelle
7
$ sed 's/-[[:alnum:]]*-[[:alnum:]]*$//' file
bucket,abc-def-ghi
bucket,dde-wwq-ooi
instance,jkl-mno-1-zzz
disk,pqr-stu-10-kuy

Dadurch werden seddie letzten beiden durch Striche getrennten Teilzeichenfolgen in jeder Zeile abgeglichen und entfernt. [[:alnum:]]stimmt mit jedem alphanumerischen Zeichen überein.

Sie können es auf kürzen

sed 's/\(-[[:alnum:]]*\)\{2\}$//' file

dh zwei Sätze von -[[:alnum:]]*ath am Ende jeder Zeile abgleichen und löschen .

Mit GNU awkkönnten Sie auch tun

$ awk -F '-' 'BEGIN { OFS=FS } { NF -= 2; print }' file
bucket,abc-def-ghi
bucket,dde-wwq-ooi
instance,jkl-mno-1-zzz
disk,pqr-stu-10-kuy

Eine NFsolche Änderung ist jedoch nicht portabel und sollte vermieden werden (es gibt keine Garantie dafür, dass der aktuelle Datensatz geändert wird). Mit BSD würde es awkzum Beispiel nicht funktionieren .

Mit Standard müssten Sie awk, ohne auf die Verwendung zurückzugreifen sub()(was nur zu imitieren wäre sed), den aktuellen Datensatz aus den Feldern neu erstellen, die Sie verwenden möchten (in unserem Fall alle bis auf die letzten beiden durch Bindestriche getrennten Felder):

$ awk -F '-' 'BEGIN { OFS=FS } { nf = split($0,a) - 2; $0=""; for (i=1; i<=nf; ++i) $i = a[i]; print }' file
bucket,abc-def-ghi
bucket,dde-wwq-ooi
instance,jkl-mno-1-zzz
disk,pqr-stu-10-kuy
Kusalananda
quelle
4

Mit revund cut:

rev file | cut -d'-' -f3- | rev

Kehren Sie die Zeilen um, cutFeld 3 bis zum Ende der Zeile, und kehren Sie den Text wieder um.


Mit grep(und PCRE):

grep -Po '.*(?=(-[^-]*){2}$)' file
  • -PVerwenden Sie Perl-kompatible reguläre Ausdrücke mit einem positiven Lookahead (?...), der zwei Übereinstimmungen -gefolgt von Nicht- -Zeichen enthält
  • -o Drucken Sie nur übereinstimmende Teile
Freddy
quelle
4
$ perl -F- -lane 'print join "-", @F[0..($#F-2)]' googleapis.txt
bucket,abc-def-ghi
bucket,dde-wwq-ooi
instance,jkl-mno-1-zzz
disk,pqr-stu-10-kuy

Dadurch wird jede Eingabezeile @Fmithilfe eines Trennzeichens automatisch in ein Array aufgeteilt -.

Anschließend wird ein Array-Slice aller bis auf die letzten beiden Felder gedruckt, die mit -Zeichen wieder verbunden werden.

cas
quelle
1

Sie können dies auf verschiedene Arten tun, wie hier gezeigt:

$ perl -F- -pale '$"="-";$#F-=2;$_="@F"' file

Teilen Sie die Linien auf einem Bindestrich, setzen Sie den Array-Element-Joiner auf Strich, schneiden Sie die letzten beiden Elemente ab und setzen Sie die aktuelle Linie auf ein Array, das mit Bindestrichen verbunden ist.

$ awk -F- '{
   t = $1
   for ( i=2; i<NF-1; i++ ) t = t FS $i
   $0 = t
}1' file

Dies ist mit einfacher Zeichenfolgenverarbeitung:

$ perl -lne 'print substr($_, 0, rindex($_,"-",-1+rindex($_,"-")))' file

.

$ sed -ne '
   y/-/\n/
   :a;h;s/\n/-/;/\n.*\n/ba
   g;P
' file

Ergebnisse:

bucket,abc-def-ghi
bucket,dde-wwq-ooi
instance,jkl-mno-1-zzz
disk,pqr-stu-10-kuy
Rakesh Sharma
quelle