Wie erhalte ich das erste Wort einer Zeichenfolge?

43

Wenn ich 'echo *' bekomme ich die folgende Ausgabe:

file1 file2 file3 ...

Ich möchte das erste Wort herausgreifen. Wie kann ich vorgehen?

vdegenne
quelle
1
@mattdm Using lsfunktioniert nicht, wenn einer der Dateinamen ein Leerzeichen enthält.
Hilfemethode
2
Wie definierst du ein Wort ? Wenn die erste Datei ist Sunset on a beach.jpg, sollte es sein Sunsetoder der gesamte Dateiname? Was ist Sea, sex and sun.ogg? Sea, Sea,Oder der gesamte Dateiname?
Stéphane Chazelas
@mattdm ls | head -1gibt mir zufällige Dinge wie a.patch p.pydas, was nicht das erste Wort ist und nicht einmal Dateien in alphabetischer Reihenfolge.
Phuclv

Antworten:

52

Sie können es durch awk leiten und es das erste Wort wiedergeben lassen

echo * | head -n1 | awk '{print $1;}'

oder du schneidest den String auf und wählst das erste Wort:

echo *  | head -n1 | cut -d " " -f1

oder Sie leiten es durch und lassen es alles bis auf das erste Wort entfernen

echo * | head -n1 | sed -e 's/\s.*$//'

Fügte hinzu | head -n1, um Nitpicker zufriedenzustellen. Wenn Ihre Zeichenfolge Zeilenumbrüche enthält, | head -n1wird zuerst die erste Zeile ausgewählt, bevor die wichtigen Befehle das erste Wort aus der an sie übergebenen Zeichenfolge auswählen.

Bananguin
quelle
1
Das würde das erste Wort jeder Zeile zurückgeben, nicht das erste Wort.
Stéphane Chazelas
2
Ich frage mich, wie viele Zeilen echo *generiert
Bananguin
Dies hängt davon ab, wie viele Dateien Zeilenumbrüche enthalten oder je nach Umgebung oder wie die Bash kompiliert wurde oder ob eine Datei mit dem Namen -eoder -ee... in der Liste aufgeführt ist und wie \noft sie in einem Dateinamen enthalten ist. Wenn eine Datei aufgerufen wird -n, gibt sie möglicherweise nicht einmal eine Zeile zurück ...
Stéphane Chazelas
Nun, wir sprechen immer noch von bash und 1. normalerweise übergibt bash einen String mit Newlines nicht als einen String mit Newlines. 2. Es ist sehr schwierig und ungewöhnlich (unmöglich?), Einen Newline in einem Dateinamen zu haben. 3. a \ n in Ein Dateiname wird als \ n angezeigt. 4. 3 gilt für Dateinamen, die mit - 5 beginnen. Selbst wenn Sie mit -n oder -e aufgerufen werden, wird stdout geöffnet und geschlossen, wenn dies erledigt ist. Natürlich wird eine Zeile zurückgegeben und um Mindestens eine Zeichenfolge, für diese Angelegenheit 6. Ich habe meinen Rat bearbeitet, um zumindest das mehrzeilige Problem zu lösen
Bananguin
1
Alle 5 Punkte sind falsch. Versuchen Sie es in einem leeren Verzeichnis: touch '$a\nb' 'a\nb'; env BASHOPTS=xpg_echo bash -c 'echo * | wc -l'( xpg_echoist aktiviert, wo bashimmer Unix-konform sein muss). Und in einem anderen leeren Verzeichnis: touch ./-n; bash -c 'echo * | wc -l'. Eine Zeile ist eine Folge von Zeichen, die durch ein Zeilenumbruchzeichen abgeschlossen werden. Wenn echokein Zeilenumbruchzeichen ausgegeben wird, wird keine Zeile ausgegeben. Verhalten von Text - Utilities wie cut, awkoder sedist nicht spezifiziert , wenn die Eingabe zusätzliche Zeichen hat nach dem letzten Newline - Zeichen und das Verhalten gegenüber Implementierungen variieren.
Stéphane Chazelas
18

Angenommen, eine Posixy-Shell ( /bin/shoder /bin/bashkann dies tun)

all=$(echo *)
first=${all%% *}

Das Konstrukt ${all%% *}ist ein Beispiel für das Entfernen von Teilzeichenfolgen . Das %%Mittel löscht die längste Übereinstimmung von *(ein Leerzeichen, gefolgt von irgendetwas) vom rechten Ende der Variablen all. Weitere Informationen zur Manipulation von Zeichenfolgen finden Sie hier .

Diese Lösung setzt voraus, dass das Trennzeichen ein Leerzeichen ist. Wenn Sie dies mit Dateinamen tun, wird dies durch Leerzeichen aufgehoben.

starfry
quelle
Schön. Aber ich mochte die einfache und non-hacky andere Version mit headundcut
Anwar
4
IMO, Head, Cut & Sed sind weniger einfach. Warum ein anderes Werkzeug erzeugt wird, wenn die eingebaute Parameterersetzung die Arbeit effizient erledigt? Diese Antwort ist die effizienteste und übertragbarste Methode, um das erste Wort einer Liste von durch Leerzeichen getrennten Wörtern (nach denen alle OPs gefragt haben) herauszusuchen.
Juan
7

Angenommen, Sie möchten wirklich den ersten Dateinamen und nicht das erste Wort , dann haben wir einen Weg, der bei Leerzeichen nicht bricht:

shopt -s nullglob
files=(*)
printf '%s\n' "${files[0]}"
Chris Down
quelle
1
Das erste Wort wäre auch einfach:files=($(echo *))
Hauke ​​Laging
2
Es würde auf "-n", "-e", "-ne", "-Enenene" ... und abhängig von der bashKompilierung oder der Umgebung, möglicherweise jedoch auf Backslash-Zeichen, aufbrechen.
Stéphane Chazelas
2
@HaukeLaging, Sie müssen das Globbing deaktivieren. Wie:, text=$(echo *); set -f; files=($text)sonst könnten mehr Wildcards erweitert werden.
Stéphane Chazelas
3
undfiles=$(echo *); echo ${files%% *}
vdegenne
1
@memnoch_proxy Bei Dateinamen, die Leerzeichen enthalten, tritt ein Fehler auf. Verwenden Sie diese Option mit Vorsicht.
Chris Down
5

Sie können die Positionsparameter verwenden

set -- *
echo "$1"
Glenn Jackman
quelle
3
Beachten Sie, dass dadurch alle anderen Argumente für Ihr Skript zerstört werden, sofern sie nicht in einem Hilfsbereich ausgeführt werden. Es wird auch erweitert, *wenn sich keine Dateien im Verzeichnis befinden.
Chris Down
shopt -s nullglobwürde damit umgehen
Glenn Jackman
3

Aktivieren Sie eine der folgenden Alternativen:

$ FILE=($(echo *))
$ FILE=$(echo * | grep -o "^\S*")
$ FILE=$(echo * | grep -o "[^ ]*")
$ FILE=$(find . -type f -print -quit)

Dann können Sie es über ausdrucken echo $FILE.

Siehe auch: grepDas einzige erste Wort aus der Ausgabe?

Kenorb
quelle
1

Den ganzen ersten Dateinamen erhalten:

shopt -s nullglob
printf '%s\000' * | grep -z -m 1 '^..*$'
printf '%s\000' * | ( IFS="" read -r -d "" var; printf '%s\n' "$var" )
markle
quelle