@MestreLion Oft lesen Leute eine Frage, um eine Lösung für eine Variation eines Problems zu finden. Dieser beginnt mit der falschen Prämisse, cutdie etwas unterstützt, was er nicht unterstützt. Aber ich fand es nützlich, weil es den Leser dazu zwingt, Code zu betrachten, der leichter zu befolgen ist. Ich wollte eine schnelle, einfache Art und Weise zu nutzen , cutohne für mehrere Syntaxen zu verwenden , zu benötigen awk, grep, sedetc. Die revSache hat den Trick; sehr elegant und etwas, an das ich nie gedacht habe (auch wenn es für andere Situationen klobig ist). Ich habe auch gerne die anderen Ansätze aus den anderen Antworten gelesen.
Beejor
3
Kam hier ein echtes Problem: Ich möchte alle verschiedenen Dateierweiterungen in einem Quellbaum finden, um eine .gitattributes-Datei mit zu aktualisieren. So find | cut -d. -f<last>ist die natürliche Neigung
Studog
Antworten:
679
Sie könnten so etwas versuchen:
echo 'maps.google.com'| rev | cut -d'.'-f 1| rev
Erläuterung
rev kehrt "maps.google.com" um moc.elgoog.spam
cut verwendet Punkt (dh '.') als Trennzeichen und wählt das erste Feld aus moc
Zuletzt kehren wir es noch einmal um, um zu bekommen com
Es verwendet nicht nur, cutsondern es ist ohne sedoder. awkAlso, was OP denken?
Jayesh Bhoi
7
@tom OP hat in den letzten Stunden mehr Fragen gestellt als nur diese. Aufgrund unserer Interaktionen mit dem OP wissen wir, dass awk / sed / etc. sind in seinen Hausaufgaben nicht erlaubt, aber ein Hinweis auf rev wurde nicht gemacht. Es war also einen
Versuch
4
@zfus Ich verstehe. Vielleicht möchten Sie danach noch einen kleben rev.
Tom
17
doppelt revtoll ideal!
Ford Guo
6
Genial, einfach, perfekt, danke auch für die Erklärung - nicht genug Leute, die jeden Schritt in langen Ketten von Rohrleitungsbefehlen erklären
Pete
128
Verwenden Sie eine Parametererweiterung. Dies ist viel effizienter als jede Art von externem Befehl cut(oder grep).
@ErwinWessels: Weil Bash sehr langsam ist. Verwenden Sie Bash, um Pipelines auszuführen, und nicht, um Daten in großen Mengen zu verarbeiten. Ich meine, das ist großartig, wenn Sie bereits eine Textzeile in einer Shell-Variablen haben oder wenn Sie while IFS= read -ra array_var; do :;done <(cmd)ein paar Zeilen verarbeiten möchten . Aber für eine große Datei ist rev | cut | rev wahrscheinlich schneller! (Und natürlich wird awk schneller sein.)
Peter Cordes
2
@PeterCordes, awk wird für eine große Datei zwar schneller sein, aber es sind einige Eingaben erforderlich, um die Startkosten mit konstantem Faktor zu überwinden. (Es gibt auch Shells - wie ksh93 - mit einer Leistung, die näher an awk liegt, wobei die in dieser Antwort angegebene Syntax weiterhin gültig ist. Bash ist außergewöhnlich träge, aber nicht annähernd die einzige verfügbare Option.)
Charles Duffy
1
Danke @PeterCordes; Wie immer hat jedes Tool seine Anwendungsfälle.
Erwin Wessels
1
Dies ist bei weitem die schnellste und präziseste Methode, um eine einzelne Variable in einem bashSkript zu kürzen (vorausgesetzt, Sie verwenden bereits ein bashSkript). Sie müssen nichts Externes anrufen.
Ken Sharp
1
@Balmipour, ... jedoch revist spezifisch für was auch immer OS Sie verwenden, zur Verfügung stellt - es auf allen UNIX - Systemen nicht standardisiert ist. In der Kapitelliste finden Sie den Abschnitt POSIX zu Befehlen und Dienstprogrammen - er ist nicht vorhanden. Und ${var##prefix_pattern}ist nicht in der Tat bash-spezifische; Es ist im POSIX sh-Standard enthalten , siehe Ende von Abschnitt 2.6.2 (verknüpft). Im Gegensatz dazu revist es immer auf jeder kompatiblen Shell verfügbar.
Charles Duffy
89
Es ist nicht möglich, nur zu verwenden cut. Hier ist ein Weg mit grep:
Um das Gegenteil zu tun und alles außer dem letzten Feld zu finden, tun Sie:grep -o '^.*,'
Ariel
2
Dies war besonders nützlich, da revin meinem Fall ein Problem mit Multibyte-Unicode-Zeichen hinzugefügt wurde.
Brice
3
Ich habe versucht, dies in MinGW zu tun, aber meine grep-Version unterstützt -o nicht. Daher habe ich verwendet, sed 's/^.*,//'wodurch alle Zeichen bis einschließlich des letzten Kommas durch eine leere Zeichenfolge ersetzt werden.
TamaMcGlinn
46
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. -F wenn für Feldtrennzeichen NF die Anzahl der Felder ist (steht auch für den Index des letzten)
Dies ist universell und funktioniert jedes Mal genau wie erwartet. In diesem Szenario entspricht die Verwendung cutzur Erzielung der endgültigen Ausgabe des OP der Verwendung eines Löffels zum "Schneiden" des Steaks (Wortspiel beabsichtigt :)). awkist das Steakmesser.
Hickory420
3
Vermeiden Sie unnötige Verwendung echo, da dies das Skript für lange Dateien verlangsamen kann awk -F. '{print $NF}' <<< 'maps.google.com'.
Anil_M
14
Es gibt mehrere Möglichkeiten. Sie können dies auch verwenden.
Bei Verwendung 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 als echte Bedingung dieser Lösung niemals Teil sein.
Ja, eine sehr dumme Lösung, aber die einzige, die die Kriterien erfüllt, denke ich.
Nett. Nimm einfach das letzte '.' aus "string" und das funktioniert.
Matt
2
Ich liebe es, wenn jeder sagt, etwas sei unmöglich und dann mischt sich jemand mit einer funktionierenden Antwort ein. Auch wenn es in der Tat sehr dumm ist.
Beejor
Man könnte cut -f2-in einer Schleife iterieren , bis sich die Ausgabe nicht mehr ändert.
Loa_in_
4
Wenn Ihre Eingabezeichenfolge keine Schrägstriche enthält, können Sie basenameeine Unterschale verwenden:
Dies wird nicht verwendet sedoder awkes wird auch nicht verwendet cut, daher bin ich mir nicht ganz sicher, ob es sich um eine Antwort auf die Frage handelt, wie sie formuliert ist.
Dies funktioniert nicht gut, wenn Eingabezeichenfolgen verarbeitet werden, die Schrägstriche enthalten können. Eine Problemumgehung für diese Situation besteht darin, den Schrägstrich durch ein anderes Zeichen zu ersetzen, von dem Sie wissen, dass es nicht Teil einer gültigen Eingabezeichenfolge ist. Beispielsweise ist das |Zeichen pipe ( ) auch in Dateinamen nicht zulässig. Dies würde also funktionieren:
Sie benötigen doppelte Anführungszeichen um die Argumente, echodamit dies zuverlässig und robust funktioniert. Siehe stackoverflow.com/questions/10067266/…
Tripleee
0
Wenn Sie eine Datei mit dem Namen filelist.txt haben, bei der es sich um Listenpfade wie die folgenden handelt: c: /dir1/dir2/file1.h c: /dir1/dir2/dir3/file2.h
dann können Sie dies tun: rev filelist.txt | cut -d "/" -f1 | rev
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;dowhile[["$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.
Meh, warum nicht einfach den Schnitt komplett entfernen und nur bash verwenden ... x] while read -r line; do echo ${line/*;}; done <input.fileergibt das gleiche Ergebnis.
Kaffe Myers
-1
Mir wurde klar, dass es funktioniert, wenn wir nur sicherstellen, dass ein abschließendes Trennzeichen vorhanden ist. In meinem Fall habe ich also Komma- und Leerzeichen. Ich füge am Ende ein Leerzeichen hinzu.
cut
Kommando :)? Warum nicht irgendwelche anderen Linux-Befehle?sed
oderawk
:perl -pe 's/^.+\s+([^\s]+)$/$1/'
.cut
die etwas unterstützt, was er nicht unterstützt. Aber ich fand es nützlich, weil es den Leser dazu zwingt, Code zu betrachten, der leichter zu befolgen ist. Ich wollte eine schnelle, einfache Art und Weise zu nutzen ,cut
ohne für mehrere Syntaxen zu verwenden , zu benötigenawk
,grep
,sed
etc. Dierev
Sache hat den Trick; sehr elegant und etwas, an das ich nie gedacht habe (auch wenn es für andere Situationen klobig ist). Ich habe auch gerne die anderen Ansätze aus den anderen Antworten gelesen.find | cut -d. -f<last>
ist die natürliche NeigungAntworten:
Sie könnten so etwas versuchen:
Erläuterung
rev
kehrt "maps.google.com" ummoc.elgoog.spam
cut
verwendet Punkt (dh '.') als Trennzeichen und wählt das erste Feld ausmoc
com
quelle
cut
sondern es ist ohnesed
oder.awk
Also, was OP denken?rev
.rev
toll ideal!Verwenden Sie eine Parametererweiterung. Dies ist viel effizienter als jede Art von externem Befehl
cut
(odergrep
).In BashFAQ # 100 finden Sie eine Einführung in die native String-Manipulation in Bash.
quelle
while IFS= read -ra array_var; do :;done <(cmd)
ein paar Zeilen verarbeiten möchten . Aber für eine große Datei ist rev | cut | rev wahrscheinlich schneller! (Und natürlich wird awk schneller sein.)bash
Skript zu kürzen (vorausgesetzt, Sie verwenden bereits einbash
Skript). Sie müssen nichts Externes anrufen.rev
ist spezifisch für was auch immer OS Sie verwenden, zur Verfügung stellt - es auf allen UNIX - Systemen nicht standardisiert ist. In der Kapitelliste finden Sie den Abschnitt POSIX zu Befehlen und Dienstprogrammen - er ist nicht vorhanden. Und${var##prefix_pattern}
ist nicht in der Tat bash-spezifische; Es ist im POSIX sh-Standard enthalten , siehe Ende von Abschnitt 2.6.2 (verknüpft). Im Gegensatz dazurev
ist es immer auf jeder kompatiblen Shell verfügbar.Es ist nicht möglich, nur zu verwenden
cut
. Hier ist ein Weg mitgrep
:Ersetzen Sie das Komma durch andere Trennzeichen.
quelle
grep -o '^.*,'
rev
in meinem Fall ein Problem mit Multibyte-Unicode-Zeichen hinzugefügt wurde.sed 's/^.*,//'
wodurch alle Zeichen bis einschließlich des letzten Kommas durch eine leere Zeichenfolge ersetzt werden.Ohne awk? ... Aber mit awk ist es so einfach:
AWK ist ein viel leistungsfähigeres Werkzeug, das Sie in Ihrer Tasche haben können. -F wenn für Feldtrennzeichen NF die Anzahl der Felder ist (steht auch für den Index des letzten)
quelle
cut
zur Erzielung der endgültigen Ausgabe des OP der Verwendung eines Löffels zum "Schneiden" des Steaks (Wortspiel beabsichtigt :)).awk
ist das Steakmesser.echo
, da dies das Skript für lange Dateien verlangsamen kannawk -F. '{print $NF}' <<< 'maps.google.com'
.Es gibt mehrere Möglichkeiten. Sie können dies auch verwenden.
Offensichtlich sollte die Leerzeichen-Eingabe für den Befehl tr durch das von Ihnen benötigte Trennzeichen ersetzt werden.
quelle
Dies ist die einzig mögliche Lösung, um nur Schnitt zu verwenden:
Bei Verwendung 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 als echte Bedingung dieser Lösung niemals Teil sein.
Ja, eine sehr dumme Lösung, aber die einzige, die die Kriterien erfüllt, denke ich.
quelle
cut -f2-
in einer Schleife iterieren , bis sich die Ausgabe nicht mehr ändert.Wenn Ihre Eingabezeichenfolge keine Schrägstriche enthält, können Sie
basename
eine Unterschale verwenden:Dies wird nicht verwendet
sed
oderawk
es wird auch nicht verwendetcut
, daher bin ich mir nicht ganz sicher, ob es sich um eine Antwort auf die Frage handelt, wie sie formuliert ist.Dies funktioniert nicht gut, wenn Eingabezeichenfolgen verarbeitet werden, die Schrägstriche enthalten können. Eine Problemumgehung für diese Situation besteht darin, den Schrägstrich durch ein anderes Zeichen zu ersetzen, von dem Sie wissen, dass es nicht Teil einer gültigen Eingabezeichenfolge ist. Beispielsweise ist das
|
Zeichen pipe ( ) auch in Dateinamen nicht zulässig. Dies würde also funktionieren:quelle
Das Folgende implementiert den Vorschlag eines Freundes
quelle
echo
damit dies zuverlässig und robust funktioniert. Siehe stackoverflow.com/questions/10067266/…Wenn Sie eine Datei mit dem Namen filelist.txt haben, bei der es sich um Listenpfade wie die folgenden handelt: c: /dir1/dir2/file1.h c: /dir1/dir2/dir3/file2.h
dann können Sie dies tun: rev filelist.txt | cut -d "/" -f1 | rev
quelle
Hinzufügen eines Ansatzes zu dieser alten Frage nur zum Spaß:
Neben Bash wird nur Cut verwendet. Nun, und Echo, denke ich.
quelle
while read -r line; do echo ${line/*;}; done <input.file
ergibt das gleiche Ergebnis.Mir wurde klar, dass es funktioniert, wenn wir nur sicherstellen, dass ein abschließendes Trennzeichen vorhanden ist. In meinem Fall habe ich also Komma- und Leerzeichen. Ich füge am Ende ein Leerzeichen hinzu.
quelle
ans="a, b, c"
produziertb
, was nicht den Anforderungen von "Anzahl der Felder ist unbekannt oder ändert sich mit jeder Zeile" entspricht .