Come ottenere la prima parola di una stringa?


43

Quando 'echo *' ottengo il seguente output:

file1 file2 file3 ...

Quello che voglio è scegliere la prima parola. Come posso procedere?


1
@mattdm L'uso lsnon funzionerà se uno dei nomi dei file contiene uno spazio.
helpermethod,

2
Come si definisce la parola ? Se il primo file è Sunset on a beach.jpg, dovrebbe essere Sunseto l'intero nome del file? Che dire Sea, sex and sun.ogg? Sea, Sea,O l'intero nome del file?
Stéphane Chazelas,

@mattdm ls | head -1mi dà cose casuali come quella a.patch p.pyche non è la prima parola e nemmeno i file in ordine alfabetico.
phuclv,

Risposte:


52

Puoi instradarlo attraverso awk e farlo eco alla prima parola

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

oppure tagli la stringa e selezioni la prima parola:

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

o lo installi attraverso sed e gli fai rimuovere tutto tranne la prima parola

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

Aggiunto il | head -n1per soddisfare i nitpickers. Nel caso in cui la tua stringa contenga nuove righe | head -n1selezionerà la prima riga prima che i comandi importanti selezionino la prima parola dalla stringa passata ad essa.


1
Restituirebbe la prima parola di ogni riga, non la prima parola.
Stéphane Chazelas,

2
mi chiedo quante righe echo *generi
Bananguin,

Dipende da quanti file hanno caratteri di nuova riga nel loro nome o in base all'ambiente o come è stato compilato bash o se un file chiamato -eo -ee... appare nell'elenco, quante volte \nappare nel nome di un file. Se c'è un file chiamato -n, potrebbe anche non restituire alcuna riga ...
Stéphane Chazelas,

Bene, stiamo ancora parlando bash e 1. di solito bash non passa una stringa con newline come una stringa con nuove righe 2. è molto difficile e insolito (impossibile?) Avere una nuova riga in un nome file 3. a \ n in un nome di file apparirà come \ n 4. 3 vale per i nomi di file che iniziano con - 5. anche quando chiamato con -n o -e echo aprirà stdout e lo chiuderà quando sarà fatto, quindi ovviamente restituirà una riga, e in almeno una stringa, del
resto

1
Tutti i 5 punti sono falsi. Prova in una directory vuota: touch '$a\nb' 'a\nb'; env BASHOPTS=xpg_echo bash -c 'echo * | wc -l'( xpg_echoè abilitata ovunque bashsia necessario essere conforme a Unix). E in un'altra directory vuota: touch ./-n; bash -c 'echo * | wc -l'. Una linea è una sequenza di caratteri terminata da un carattere di nuova riga. Se echonon genera un carattere di nuova riga, non genera alcuna riga. Il comportamento di utilità di testo come cut, awko sednon è specificato se l'input ha caratteri extra dopo l'ultimo carattere di nuova riga e il comportamento varia tra le implementazioni.
Stéphane Chazelas,

18

Supponendo una shell posixy ( /bin/sho /bin/bashpuò farlo)

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

Il costrutto ${all%% *}è un esempio di rimozione della sottostringa . I %%mezzi eliminano la corrispondenza più lunga di *(uno spazio seguito da qualsiasi cosa) dall'estremità destra della variabile all. Puoi leggere di più sulla manipolazione delle stringhe qui .

Questa soluzione presuppone che il separatore sia uno spazio. Se lo stai facendo con i nomi dei file, qualsiasi spazio verrà interrotto.


Ben fatto. Ma mi è piaciuta l'altra versione semplice e non complicata con headecut
Anwar,

4
IMO, head, cut & sed sono meno semplici. Perché generare un altro strumento quando la sostituzione dei parametri integrata esegue il lavoro in modo efficiente. Questa risposta è il modo più efficiente e portatile per selezionare la prima parola di un elenco di parole separate da spazio (che è tutto l'OP richiesto).
Juan,

7

Supponendo che tu voglia davvero il primo nome file e non la prima parola , ecco un modo che non si rompe nello spazio bianco:

shopt -s nullglob
files=(*)
printf '%s\n' "${files[0]}"

1
Anche la prima parola sarebbe facile:files=($(echo *))
Hauke ​​Laging,

2
Si romperà su "-n", "-e", "-ne", "-Enenene" ... e, a seconda di come è bashstato compilato o dell'ambiente, possibilmente su caratteri di barra rovesciata.
Stéphane Chazelas,

2
@HaukeLaging, dovresti disabilitare il globbing. Come text=$(echo *); set -f; files=($text):, altrimenti potrebbero essere espansi più caratteri jolly.
Stéphane Chazelas,

3
efiles=$(echo *); echo ${files%% *}
vdegenne,

1
@memnoch_proxy Si romperà su nomi di file contenenti spazi bianchi, usalo con cautela.
Chris Down,

5

È possibile utilizzare i parametri posizionali

set -- *
echo "$1"

3
Tieni presente che ciò distruggerà qualsiasi altro argomento del tuo script, a meno che non venga eseguito in un ambito ausiliario. Si espanderà anche a *se non ci sono file nella directory.
Chris Down,

shopt -s nullgloblo farebbe
Glenn Jackman,

3

Controlla una delle seguenti alternative:

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

Quindi puoi stamparlo tramite echo $FILE.

Vedi anche: grepl'unica prima parola dall'output?



1

Ottenere l'intero nome del primo file:

shopt -s nullglob
printf '%s\000' * | grep -z -m 1 '^..*$'
printf '%s\000' * | ( IFS="" read -r -d "" var; printf '%s\n' "$var" )
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.