Bash - Sequenza di numeri nella stessa riga


20

Conosco il comando seqper generare una sequenza di numeri interi, uno per riga, ma vorrei porre due domande:

  1. È possibile scrivere i numeri della sequenza nella stessa riga?

  2. È possibile creare una stringa composta dalla sequenza di numeri separati da uno spazio bianco?


La shell tratta le nuove linee come gli spazi come separatori di argomenti. Quindi, mentre seq ha un argomento separatore, e la cosa ancora più semplice da dire è soloecho $(seq 1 10)
user3188445

1
@ user3188445, è l'operatore split + glob che lo fa (che utilizza la variabile speciale IFS che per impostazione predefinita contiene spazio e newline ma può essere modificato), è separato dalla tokenizzazione delle parole effettuata dalla shell.
Stéphane Chazelas,

Risposte:



21

GNU seqaccetta l' -sopzione separator ( ):

$ seq -s ' ' 1 5
1 2 3 4 5

$ var="$(seq -s ' ' 1 5)"
$ echo "$var"
1 2 3 4 5

1
echo $(seq 5)funziona bene.

13

Portatile per tutte le shell e qualsiasi sistema che abbia seq (poiché questa domanda è taggata)

Se start è 1:

$ echo $(seq 10)
1 2 3 4 5 6 7 8 9 10

Altrimenti:

$ echo $(seq 5 10)
5 6 7 8 9 10

Con bc:

$ echo $(echo "for (i=0;i<=1000;i++) i"| bc)

In bash

echo {1..10}

Nota:

Questa soluzione di eco funziona se il valore di IFS contiene una nuova riga, cosa che fa di default.
Per impostazione predefinita, IFS è impostato sulla sequenza <spazio> <tab> <nuova> . E viene ripristinato per ogni inizio pulito della shell. Ma, se hai qualche dubbio sul fatto che potrebbe essere cambiato in qualche caso estremo, abbiamo diverse soluzioni.

Sotto bash, zsh, ksh usa solo: IFS = $ '\ t \ n' (salta tutto il resto di questa risposta).


Tuttavia, il ripristino del valore di IFS in sh può essere complesso. Leggi i dettagli completi qui .

Disinserire IFS.

$ unset IFS; echo $(seq 5 10)                           #Always work.

funzionerà sempre. A condizione che non ci sia un codice sottostante (o script secondari) che necessiti di un set IFS, come uno script che lo fa OldIFS="$IFS".

Soluzione corretta.

Usando un trucco per sh:

sh -c 'IFS="$(printf " \t\nx")"; IFS="${IFS%x}"; printf "$IFS"|xxd'  # correct.

I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
terdon

1
La maggior parte delle implementazioni sh ignorerà l'IFS trovato nell'ambiente (le eccezioni sono alcuni derivati ​​di cenere, versioni molto vecchie di alcune shell Bourne e versioni recenti di elegante). Si noti che si può semplicemente fare IFS='<space><tab><newline>' dove coloro <space>, <tab>, <newline>sono i corrispondenti caratteri letterali.
Stéphane Chazelas,


0
seq 10 |xargs

...o...

seq 10 |paste -s -

Entrambi i comandi precedenti separeranno i numeri interi per spazio bianco. xargsil valore predefinito è l'imitazione /bin/echoe quindi ogni numero intero è separato da un singolo spazio. Per impostazione predefinita, tuttavia, avrà una lunghezza massima della riga di comando di 128 K. Puoi regolare questo ...

seq 100000 | xargs -s2093009 | wc -l

... stampe 1. I il valore -squi non è arbitrario - l'ho ottenuto dopo aver provato un valore più alto (che apparentemente ha funzionato comunque) ma in seguito ha xargsstampato il messaggio utile:

-s value should be <2093010

pasteè una delle due utilità (a mia conoscenza) sanzionate con POSIX per la gestione di linee di lunghezza arbitraria:

pasteutilizzo dell'applicazione specifica :

La maggior parte delle utility standard funziona su file di testo . L' cututilità può essere utilizzata per trasformare file con lunghezze di riga arbitrarie in un set di file di testo contenenti gli stessi dati. L' pasteutilità può essere utilizzata per creare (o ricreare) file con lunghezze di linea arbitrarie.

file di testo

Un file che contiene caratteri organizzati in zero o più righe. Le righe non contengono caratteri NUL e nessuna può superare i {LINE_MAX}byte di lunghezza, incluso il \ncarattere ewline. Sebbene POSIX.1-2008 non distingua tra file di testo e file binari (vedere lo standard ISO C) , molte utility producono output prevedibili o significativi solo quando si opera su file di testo. Le utility standard che hanno tali restrizioni specificano sempre i file di testo nelle loro sezioni STDIN o INPUT FILES .

pasteil valore predefinito è un delimitatore di tabulazione e quindi ci sarà una tabulazione tra ciascun numero intero dopo il secondo comando. Puoi...

seq 10 |paste -sd ' ' - 

... usa l' -dinterruttore elimiter per modificare quel comportamento,


seq 10 | xargsfunziona bene, ma a causa dei limiti della riga di comando, seq 100000 | xargsgenera 5 \nlinee delimitate (sul mio sistema)
Peter.O

@ Peter.O - paste and cut` sono le due utility sanzionate POSIX per lavorare con linee di lunghezza arbitraria. Detto questo, xargs | xargsè un'opzione. Oppureseq 100000|tr \\n \
mikeserv il

I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
terdon

@BinaryZebra - no non lo fa - non come pensi che faccia. Perché non provare a impostare $IFSun numero? E comunque nella bashsua lentezza divina. Nella tua risposta di cui parli sh- non hai nemmeno bisogno di impostare $IFSin quel contesto - verrà trasmesso attraverso l'ambiente se è impostato lì. E non è più breve di quello seq 100000|paste -sche lo batte in termini di prestazioni 5: 1. E pastenon viene con nessun gotchas.
Mikeserv,

@BinaryZebra - dai, perché dovrei mentire? Ho un profilo di risposta considerevole su questo sito perché mi diverto a diffondere disinformazione? O forse è perché mi piace aiutare le persone e godere della sfida dell'apprendimento mentre lo faccio? Quale pensi sia più plausibile? Mi piace $IFS- lo uso sempre - ma non lo uso a meno che non lo imposti e nemmeno tu dovresti. Soprattutto non dovresti raccomandare a estranei casuali che non conoscono meglio che dovrebbero farlo. Non lasciarlo al caso: è un programma per computer. È un bug se si comporta inaspettatamente: perché permetterlo?
Mikeserv,
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.