IFS, равный символу новой строки, не работает в bash - PullRequest
0 голосов
/ 03 декабря 2018

У меня есть многострочная строка, и я хочу разделить на основе \n, для которого я устанавливаю IFS=$'\n', но это не работает, я также пробовал IFS= и IFS=" ", но не повезло.Ниже приведен пример кода

IFS=$'\n' read -ra arr <<< "line1\nline2\nline3"
printf "%s\n" "${arr[@]}"
# it only generates array of length 1

Я использую Ubuntu с версией bash

GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
<http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Может кто-нибудь указать на очевидное.

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018

Основная проблема с вашей попыткой - расщепление слов не выполняется с herestring .От man bash:

Here Strings
   A variant of here documents, the format is:

          <<<word

   ... Pathname expansion and word splitting are not performed.
   The result is supplied as a single string to the command on its 
   standard input.

Bash действительно предоставляет heredoc (например, «Здесь документ» в man bash), на котором расщепление слов будет выполнен со значением по умолчанию IFS.Однако даже тогда вы все равно будете читать литерал '\n' как часть содержимого массива.Не бойтесь, bash предоставил особый способ избежать этого с опцией -t, равной readarray (a / k / a mapfile).

Короткий пример, настолько близкий, насколько яВы можете получить исходную попытку:

readarray -t arr << EOF
line1
line2
line3
EOF
declare -p arr

В результате ваши строки будут сохранены по желанию, например, вы получите:

declare -a arr='([0]="line1" [1]="line2" [2]="line3")'

Другой вариант - использовать процесс подстановки и пусть printf обеспечивает разбиение, например,

readarray -t arr < <(printf "line1\nline2\nline3\n")

Ключ для заполнения массива без включенных новых строк - readarray -t, ключ для разрешения разделения словэто избегать herestring .

0 голосов
/ 03 декабря 2018

из руководства по bash, раздел bash buildins:

read

read [-ers] [-a aname] [-d delim] [-i text] [-n nchars]
    [-N nchars] [-p prompt] [-t timeout] [-u fd] [name …]

One line is read from the standard input, or from the file descriptor fd supplied as an argument to the -u option, 

и разделитель строк можно указать с помощью -d

-d delim

The first character of delim is used to terminate the input line, rather than newline.

Обратите внимание, что после пустого аргумента -d '' разделителем строки будет нулевой символ, если на входе нет нулевого символа, он может бытьиспользуется для чтения всего ввода.

Однако чтение происходит медленно даже в режиме -r.

Для больших вводов более быстрое решение может заключаться в использовании разделения слов:

input=$'line1\nline2\nline3'
IFS=$'\n';set -f;arr=($input);set +f;IFS=$' \t\n'

примечание set -f, чтобы избежать фазы согласования глобуса.

...