bash - sostituisce lo spazio con una nuova linea


70

Come posso sostituire gli spazi con nuove righe su un input come:

/path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5 eccetera...

Per ottenere quanto segue:

/path/to/file
/path/to/file2
/path/to/file3
/path/to/file4
/path/to/file5

Nota

Sto pubblicando questa domanda per aiutare altri utenti, non è stato facile trovare una risposta utile su UNIX SE finché non ho iniziato a digitare questa domanda. Successivamente ho trovato quanto segue:

Domanda correlata

Come posso trovare e sostituire con una nuova linea?



ls / path / to / | xargs echo | sed 's / \ s \ + / \ n / g'
SD.

Risposte:



20

In questo caso userei printf:

printf '%s\n' /path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5

Se ci sono spazi all'interno di uno dei percorsi, puoi citare quel percorso per evitare che venga suddiviso sugli spazi:

printf '%s\n' /path/to/file '/path/to/file with spaces' /path/to/another/file

Per trasformare il testo in generale, trè la soluzione migliore, come indicato in una risposta esistente.


1
Una breve nota dal futuro: grazie per aver pubblicato questa soluzione, è stato molto affidabile per me, rispetto all'utilizzo di "eco".
Liesmith,

5

Supponendo che tu abbia una stringa con spazi come separatori:

newline_separated=${space_separated// /$'\n'}

Tuttavia, probabilmente stai facendo la domanda sbagliata. (Non necessariamente, ad esempio, questo potrebbe apparire in un makefile.) Un elenco separato da spazi di nomi di file non funziona davvero: e se uno dei nomi di file contenesse spazi?

Se un programma riceve nomi di file come argomenti, non unirli con spazi. Utilizzare "$@"per accedervi uno per uno. Sebbene echo "$@"stampa gli argomenti con spazi in mezzo, ciò è dovuto a echo: stampa i suoi argomenti con spazi come separatori. somecommand "$@"passa i nomi dei file come argomenti separati al comando. Se si desidera stampare gli argomenti su righe separate, è possibile utilizzare

printf '%s\n' "$@"

Se hai nomi di file separati da spazi e vuoi metterli in un array per lavorarci sopra, puoi usare un'espansione variabile non quotata per dividere il valore in caratteri su IFS(dovrai disabilitare l'espansione jolly con set -f, altrimenti glob i pattern verranno espansi nel valore):

space_separated_list='/path/to/file1 /path/to/file2 /path/to/file3'
IFS=' '; set -f
eval "array=(\$space_separated_list)"
for x in "${array[@]}"; do 

Puoi incapsularlo in una funzione che ripristina l' -fimpostazione e il valore di IFSquando è fatto:

split_list () {
  local IFS=' ' flags='+f'
  if [[ $- = *f* ]]; then flags=; fi
  set -f
  eval "$1=($2)"
  set $flags
}
split_list array '/path/to/file1 /path/to/file2 /path/to/file3'
for x in "${array[@]}"; do 

Cambiando la risposta corretta a questa. Penso che sia più corretto ricercare come sono arrivato a un elenco separato da spazi e recuperare tali informazioni in un altro modo. Sarebbe bello per gli studenti come me se commenti un po 'la tua snipnet, dicendoci cosa fanno cose come l'IFS locale var o la condizione $ - = f . Quel genere di cose che una persona che usa bash poche volte non sa.
laconbass,

@laconbass Ho aggiunto una breve spiegazione. Cerca set -fe IFSnel manuale di bash se vuoi tutti i dettagli. Vedi anche unix.stackexchange.com/questions/16192/…
Gilles 'SO- smetti di essere malvagio' l'

@Guilles Quella breve spiegazione è abbastanza per me, e penso che lo sarà per molti altri. Ty per il tuo tempo
laconbass

l'impostazione IFSlocale non ha effetto
Eliran Malka

@EliranMalka Non ho idea di cosa intendi con questo. Se uno script non si comporta come pensi che dovrebbe, puoi fare una domanda qui.
Gilles 'SO- smetti di essere malvagio' il

4

Sii pragmatico, usa sed !!

sed 's/\s\+/\n/g' file

Quanto sopra dice di sostituire uno o più spazi bianchi (\ s +) con newline (\ n)

Questo è più o meno:

'substitute /one space or more/ for /newline/ globally'

1
sostituisci il cambiamento con un sostituto, ecco cosa rappresenta effettivamente la s!
Rob,

@Rob grazie, ricorda che puoi modificare le altre risposte.
MGP,

1
Se hai più spazi tra il testo, otterrai righe vuote. È necessario aggiungere un '+' dopo il \ s per indicare che si desidera abbinare almeno uno spazio come apposto esattamente a uno spazio. vale a dire. sed 's / \ s + / \ n / g'
DarkHeart

4

In alternativa a tr@laconbass, puoi anche utilizzare xargsin questo caso:

echo "/path/to/file /path/to/file2 /path/to/file3 /path/to/file4  /path/to/file5"\
| xargs -n1

Il vantaggio è che funziona anche con più spazi bianchi, il che trnon funziona.


0

Ecco come l'ho fatto:

echo "/path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5" | sed 's/ /\
'/g

Si noti l'uso del tasto Invio dopo la barra rovesciata nel sedcomando.


quali prons e contro ha sedfinito tr?
Laconbass,

Il tuo livello di comfort :-) Penso che puoi fare di più con sedun editor piuttosto che tradurre semplicemente i personaggi.
Unxnut

4
sedpuò fare molto di più, ma è assolutamente eccessivo per questo. trè lo strumento giusto per QUESTO lavoro, ma la conoscenza sede le regex torneranno sicuramente utili in seguito!
Rob,

0

Un altro approccio, supponendo che la linea sia in una variabile chiamata line:

for path in $line;do echo $path;done

Questo sfrutta il fatto che Bash divide i suoi argomenti sullo spazio bianco per impostazione predefinita e che echoaggiunge una nuova riga al suo input per impostazione predefinita.


Ho provato questo sul mio sistema Ubuntu prima di pubblicare questa domanda e non sono riuscito a farlo funzionare.
Laconbass,

0
echo word1 word2 ... | sed -e 'y/ /\n/;P;D'

è un altro metodo per trasformare le parole separate da spazio singolo in newline separate.


-1

Il seguente script è facile da capire e da usare.

cat filename | tr ' ' '\n' | tee filename

2
L'essenza della tua risposta ( tr) è la stessa della risposta accettata. Inoltre la tua risposta ha i seguenti problemi: a) il comando non è rientrato con 4 spazi (-> layout markdown) b) Il tuo uso di catè inutile (puoi sostituirlo con < filename tr ' ' '\n'). c) Il nome del file di output è uguale al nome del file di input. Con ciò crei una gara di dati.
maxschlepzig,

1
a parte l'analisi corretta di maxschlepzig, questo non è uno script, ma un gruppo di comandi connessi che hanno un nome codificato (poiché lo script dovrebbe avere un'intestazione che specifica la shell da usare e utilizzare due parametri per specificare in e output). A parte quel 2 su 3 persone nella mia famiglia non lo trovano facile da capire. Forse questo non è rappresentativo, ma tieni presente che qualcosa che tu stesso capisci (o in questo caso pensi di capire) sembra sempre facile.
Anthon,
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.