Bash - Séquence de nombres sur la même ligne


20

Je connais la commande seqpour générer une séquence d'entiers, un par ligne, mais je voudrais poser deux questions:

  1. Est-il possible d'écrire les numéros de la séquence sur la même ligne?

  2. Est-il possible de créer une chaîne composée de la séquence de nombres séparés par un espace blanc?


Le shell traite les sauts de ligne comme les espaces comme des séparateurs d'arguments. Donc, alors que seq a un argument séparateur, et la chose la plus simple à dire est justeecho $(seq 1 10)
user3188445

1
@ user3188445, c'est l'opérateur split + glob qui fait cela (qui utilise la variable spéciale IFS qui par défaut contient de l'espace et de la nouvelle ligne mais peut être modifiée), il est distinct du mot tokenization fait par le shell.
Stéphane Chazelas

Réponses:



21

GNU seqprend l' -soption 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)fonctionne bien.

13

Portable pour tous les shells et tout système qui a seq (car cette question est balisée)

Si le début est 1:

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

Autrement:

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

Avec bc:

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

En bash

echo {1..10}

Remarque:

Cette solution d'écho fonctionne si la valeur de IFS contient une nouvelle ligne, ce qu'elle fait par défaut.
Par défaut, IFS est défini sur la séquence <space><tab> <newline> . Et est réinitialisé pour chaque démarrage propre du shell. Mais, si vous craignez que cela ait changé dans certains cas extrêmes, nous avons plusieurs solutions.

Sous bash, zsh, ksh, utilisez simplement: IFS = $ '\ t \ n' (sautez tout le reste de cette réponse).


Cependant, la réinitialisation de la valeur de IFS sous sh peut être complexe. Lisez le détail complet ici .

Désactivez IFS.

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

fonctionnera toujours. À condition qu'il n'y ait pas de code ci-dessous (ou des scripts enfants) qui nécessitent un ensemble IFS, comme un script qui le fait OldIFS="$IFS".

Solution correcte.

Utiliser une astuce pour sh:

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

Les commentaires ne sont pas pour une discussion approfondie; cette conversation a été déplacée vers le chat .
terdon

1
La plupart des implémentations sh ignoreront l'IFS trouvé dans l'environnement (à l'exception de certains dérivés de ash, de très anciennes versions de certains shells Bourne et de versions récentes de snob). Notez que vous pouvez simplement faire IFS='<space><tab><newline>' où ceux <space>, <tab>, <newline>sont les caractères littéraux correspondants.
Stéphane Chazelas


0
seq 10 |xargs

...ou...

seq 10 |paste -s -

Les deux commandes ci-dessus sépareront les entiers par des espaces. xargspar défaut à imiter /bin/echoet donc chaque entier est séparé par un seul espace. Il sera par défaut à une longueur de ligne de commande maximale de 128 Ko, cependant. Vous pouvez régler cela ...

seq 100000 | xargs -s2093009 | wc -l

... imprime 1. I la valeur pour -sici n'est pas arbitraire - je l'ai obtenue après avoir essayé une valeur plus élevée (qui a apparemment fonctionné de toute façon) mais j'ai ensuite xargsimprimé le message utile:

-s value should be <2093010

pasteest l'un des deux utilitaires sanctionnés par POSIX (à ma connaissance) pour gérer les lignes de longueur arbitraire:

pasteutilisation de l'application de spécification :

La plupart des utilitaires standard fonctionnent sur des fichiers texte . L' cututilitaire peut être utilisé pour transformer des fichiers avec des longueurs de ligne arbitraires en un ensemble de fichiers texte contenant les mêmes données. L' pasteutilitaire peut être utilisé pour créer (ou recréer) des fichiers avec des longueurs de ligne arbitraires.

fichiers texte

Un fichier qui contient des caractères organisés en zéro ou plusieurs lignes. Les lignes ne contiennent pas de caractères NUL et aucune ne peut dépasser la {LINE_MAX}longueur d'octets, y compris le \ncaractère ewline. Bien que POSIX.1-2008 ne fasse pas de distinction entre les fichiers texte et les fichiers binaires (voir la norme ISO C) , de nombreux utilitaires ne produisent une sortie prévisible ou significative que lorsqu'ils fonctionnent sur des fichiers texte. Les utilitaires standard qui ont de telles restrictions spécifient toujours les fichiers texte dans leurs sections STDIN ou INPUT FILES .

pastepar défaut un délimiteur de tabulation, et donc il y aura un tabulation entre chaque entier après la deuxième commande. Vous pouvez...

seq 10 |paste -sd ' ' - 

... utilisez l' -dinterrupteur d'élimitation pour modifier ce comportement,


seq 10 | xargsfonctionne bien, mais en raison des limites de la ligne de commande, seq 100000 | xargsgénère 5 \nlignes délimitées (sur mon système)
Peter.O

@ Peter.O - paste and cut` sont les deux utilitaires sanctionnés par POSIX pour travailler avec des lignes de longueur arbitraire. Cela dit, xargs | xargsc'est une option. Ou bienseq 100000|tr \\n \
mikeserv

Les commentaires ne sont pas pour une discussion approfondie; cette conversation a été déplacée vers le chat .
terdon

@BinaryZebra - non, ce n'est pas le cas - pas comme vous le pensez. Pourquoi ne pas essayer de définir $IFSun nombre? Et dans bashsa lenteur de toute façon. Dans votre réponse, vous parlez sh- vous n'avez même pas besoin de le définir $IFSdans ce contexte - il sera transmis via l'environnement s'il y est défini. Et il n'est pas plus court que celui seq 100000|paste -squi le bat en termes de performances 5: 1. Et pastene vient pas avec aucun piège.
mikeserv

@BinaryZebra - allez, pourquoi mentirais-je? Ai-je un profil de réponse important sur ce site parce que j'aime diffuser des informations erronées? Ou peut-être que c'est parce que j'aime aider les gens et apprécier le défi d'apprendre pendant que je le fais? Selon vous, lequel est le plus plausible? J'aime $IFS- je l'utilise tout le temps - mais je ne l'utilise que si je l'ai réglé et vous non plus. Surtout, vous ne devriez pas recommander à des étrangers aléatoires qui ne connaissent pas mieux qu'ils devraient le faire. Ne le laissez pas au hasard - c'est un programme informatique. C'est un bug s'il se comporte de manière inattendue - pourquoi permettre qu'il le soit?
mikeserv
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.