Ohne mit sed
oder awk
, only cut
, wie bekomme ich das letzte Feld, wenn die Anzahl der Felder unbekannt ist oder sich mit jeder Zeile ändert?
Sie könnten so etwas versuchen:
echo 'maps.google.com' | rev | cut -d'.' -f 1 | rev
Erklärung
moc.elgoog.spam
sein.cut
verwendet Punkt als Trennzeichen und wählt das erste Feld aus, das moc
ist.com
Verwenden Sie eine Parametererweiterung. Dies ist viel effizienter als jede Art von externem Befehl, cut
(oder grep
).
data=foo,bar,baz,qux
last=${data##*,}
In BashFAQ # 100 finden Sie eine Einführung in die native String-Bearbeitung in bash.
Es ist nicht möglich, nur cut
zu verwenden. Hier ist eine Möglichkeit, grep
zu verwenden:
grep -o '[^,]*$'
Ersetzen Sie das Komma für andere Trennzeichen.
Ohne awk ... ... Aber mit awk ist es so einfach:
echo 'maps.google.com' | awk -F. '{print $NF}'
AWK ist ein viel leistungsfähigeres Werkzeug, das Sie in Ihrer Tasche haben können.
Es gibt mehrere Möglichkeiten. Sie können dies auch verwenden.
echo "Your string here"| tr ' ' '\n' | tail -n1
> here
Natürlich muss die Leerzeicheneingabe für den Befehl tr durch das Trennzeichen ersetzt werden, das Sie benötigen.
Dies ist die einzige Lösung, die nur für das Schneiden geeignet ist:
echo "s.t.r.i.n.g." | cut -d '.' -f2 - [repeat_following_part_forever_or_until_out_of_memory:] | cut -d '.' -f2-
Bei dieser Lösung kann die Anzahl der Felder tatsächlich unbekannt sein und von Zeit zu Zeit variieren. Da die Zeilenlänge jedoch LINE_MAX-Zeichen oder -Felder einschließlich des Zeichens für neue Zeilen nicht überschreiten darf, kann eine beliebige Anzahl von Feldern niemals Bestandteil der Lösung sein.
Ja, eine sehr dumme Lösung, aber die einzige, die die Kriterien erfüllt, die ich denke.
die folgenden Geräte Vorschlag eines Freundes
#!/bin/bash
rcut(){
nu="$( echo $1 | cut -d"$DELIM" -f 2- )"
if [ "$nu" != "$1" ]
then
rcut "$nu"
else
echo "$nu"
fi
}
$ export DELIM=.
$ rcut a.b.c.d
d
Wenn Sie über eine Datei namens filelist.txt verfügen, handelt es sich dabei um folgende Listenpfade: C: /dir1/dir2/file1.h
dann können Sie dies tun: rev filelist.txt | cut -d "/" -f1 | rev
Wenn Ihre Eingabezeichenfolge keine Schrägstriche enthält, können Sie basename
und eine Subshell verwenden:
$ basename "$(echo 'maps.google.com' | tr '.' '/')"
Dies verwendet nicht sed
oder awk
, aber auch cut
nicht. Daher bin ich mir nicht ganz sicher, ob sie als formulierte Antwort auf die Frage qualifiziert ist.
Dies funktioniert nicht gut, wenn Eingabezeichenfolgen verarbeitet werden, die Schrägstriche enthalten können. Um dieses Problem zu umgehen, können Sie den Schrägstrich durch ein anderes Zeichen ersetzen, von dem Sie wissen, dass es nicht Teil einer gültigen Eingabezeichenfolge ist. Zum Beispiel ist das Pipe-Zeichen (|
) auch in Dateinamen nicht zulässig, daher würde dies funktionieren:
$ basename "$(echo 'maps.google.com/some/url/things' | tr '/' '|' | tr '.' '/')" | tr '|' '/'
Hinzufügen eines Ansatzes zu dieser alten Frage nur zum Spaß:
$ cat input.file # file containing input that needs to be processed
a;b;c;d;e
1;2;3;4;5
no delimiter here
124;adsf;15454
foo;bar;is;null;info
$ cat tmp.sh # showing off the script to do the job
#!/bin/bash
delim=';'
while read -r line; do
while [[ "$line" =~ "$delim" ]]; do
line=$(cut -d"$delim" -f 2- <<<"$line")
done
echo "$line"
done < input.file
$ ./tmp.sh # output of above script/processed input file
e
5
no delimiter here
15454
info
Neben Bash wird nur Cut verwendet. Nun, und Echo, denke ich.
Ich habe erkannt, dass es funktioniert, wenn wir nur sicherstellen, dass ein nachlaufendes Trennzeichen existiert. In meinem Fall habe ich also Kommas und Leerzeichen als Trennzeichen. Ich füge am Ende ein Leerzeichen hinzu.
$ ans="a, b"
$ ans+=" "; echo ${ans} | tr ',' ' ' | tr -s ' ' | cut -d' ' -f2
b