Bash - последовательность чисел в одной строке

20

Я знаю команду seqдля генерации последовательности целых чисел, по одному на строку, но я хотел бы задать два вопроса:

  1. Можно ли записать номера последовательности в одной строке?

  2. Можно ли создать строку из последовательности чисел, разделенных пробелом?

Salsiccio
источник
Оболочка обрабатывает символы новой строки как пробелы как разделители аргументов. Таким образом, в то время как последующие имеет разделительный аргумент, и даже простое дело сказать простоecho $(seq 1 10)
user3188445
1
@ user3188445, это делает оператор split + glob (который использует специальную переменную IFS, которая по умолчанию содержит пробел и символ новой строки, но может быть изменен), он отделен от слова tokenization, выполняемого оболочкой.
Стефан Шазелас

Ответы:

21

GNU seqпринимает параметр separator ( -s):

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

$ var="$(seq -s ' ' 1 5)"
$ echo "$var"
1 2 3 4 5
heemayl
источник
1
echo $(seq 5)работает отлично.
13

Переносим для всех оболочек и любой системы, которая имеет seq (поскольку этот вопрос помечен)

Если начало 1:

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

В противном случае:

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

С бк:

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

В баш

echo {1..10}

Замечания:

Это эхо-решение работает, если значение IFS содержит символ новой строки, что он делает по умолчанию.
По умолчанию для IFS задана последовательность <пробел> <вкладка> <новая строка> . И сбрасывается при каждом чистом запуске оболочки. Но если у вас есть какие-либо опасения, что это могло измениться в каком-то крайнем угловом случае, у нас есть несколько решений.

В bash, zsh, ksh просто используйте: IFS = $ '\ t \ n' (пропустите все остальные ответы).


Однако сброс значения IFS в sh может быть сложным. Читайте полную информацию здесь .

Отключить IFS.

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

всегда будет работать При условии, что ниже не будет кода (или дочерних сценариев), для которого требуется установить IFS, например, такого сценария OldIFS="$IFS".

Правильное решение.

Используя трюк для sh:

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

источник
Комментарии не для расширенного обсуждения; этот разговор был перемещен в чат .
Тердон
1
Большинство реализаций sh игнорируют IFS, найденный в среде (за исключением некоторых производных золы, очень старых версий некоторых оболочек Борна и последних версий шикарных). Обратите внимание , что вы можете просто сделать , IFS='<space><tab><newline>' где те <space>, <tab>, <newline>являются соответствующие буквальные символы.
Стефан Шазелас
3

Использовать этот:

string="$(seq -s " " 1 10)"
Кир
источник
0
seq 10 |xargs

...или...

seq 10 |paste -s -

Обе команды выше разделят целые числа пробелами. xargsпо умолчанию имитирует /bin/echoи поэтому каждое целое число отделяется одним пробелом. По умолчанию будет использоваться максимальная длина командной строки 128 КБ. Вы можете настроить это ...

seq 100000 | xargs -s2093009 | wc -l

... печатает 1. I значение -sздесь не является произвольным - я получил его после того, как попробовал более высокое значение (которое, очевидно, работало в любом случае), но потом xargsнапечатал полезное сообщение:

-s value should be <2093010

pasteэто одна из двух (насколько мне известно) POSIX-санкционированных утилит для обработки строк произвольной длины:

pasteиспользование спецификации приложения :

Большинство стандартных утилит работают с текстовыми файлами . cutУтилита может быть использована , чтобы превратить файлы с произвольной длиной строки в набор текстовых файлов , содержащих одни и те же данные. pasteУтилита может быть использована для создания (или воссоздавать) файлы с произвольной длиной строки.

текстовые файлы

Файл, содержащий символы, организованные в ноль или более строк. Строки не содержат символов NUL, и ни одна из них не может превышать {LINE_MAX}длину в байтах, включая \nсимвол ewline. Хотя POSIX.1-2008 не делает различий между текстовыми файлами и двоичными файлами (см. Стандарт ISO C) , многие утилиты производят только предсказуемый или значимый вывод при работе с текстовыми файлами. Стандартные утилиты, имеющие такие ограничения, всегда указывают текстовые файлы в своих разделах STDIN или INPUT FILES .

pasteпо умолчанию используется разделитель табуляции, поэтому после каждого целого числа после второй команды будет вкладка. Вы можете...

seq 10 |paste -sd ' ' - 

... используйте -dпереключатель elimiter, чтобы изменить это поведение,

mikeserv
источник
seq 10 | xargsработает нормально, но из-за ограничений командной строки seq 100000 | xargsвыдает 5 \nстрок с разделителями (в моей системе)
Peter.O
@ Peter.O - paste and cut` - две санкционированные POSIX утилиты для работы со строками произвольной длины. Тем не менее, xargs | xargsэто вариант. Или иначеseq 100000|tr \\n \
mikeserv
Комментарии не для расширенного обсуждения; этот разговор был перемещен в чат .
Terdon
@BinaryZebra - нет, не так - не так, как ты думаешь. Почему бы не попробовать установить $IFSномер? И в bashлюбом случае, в своем чудовищном замедлении. В своем ответе вы говорите sh- вам даже не нужно устанавливать $IFSв этом контексте - он будет передан через среду, если он там установлен. И он не короче, чем тот, seq 100000|paste -sкоторый превосходит по производительности 5: 1. И pasteне приходит без каких-либо ошибок.
mikeserv
@BinaryZebra - ну зачем мне врать? У меня есть большой профиль ответов на этом сайте, потому что мне нравится распространять дезинформацию? Или, может быть, потому, что мне нравится помогать людям и получать удовольствие от обучения, пока я занимаюсь? Как вы думаете, что более правдоподобно? Мне нравится $IFS- я использую это все время - но я не использую это, если я не устанавливаю это, и вы не должны. Особенно вы не должны рекомендовать случайным незнакомцам, которые не знают ничего лучшего, как это следует делать. Не оставляйте это на волю случая - это компьютерная программа. Это ошибка, если она ведет себя неожиданно - зачем это разрешать?
mikeserv