2017-02-06 12 views
3

Я думал, что установка ИФС для $'\n' бы помочь мне в чтении всего файла в массив, например:Когда я устанавливаю IFS для новой строки в Bash?

IFS=$'\n' read -r -a array < file 

Однако вышеприведенная команда считывает только первую строку файла в первый элемент массива , и ничего больше.

Даже это читает только первую строку в массив:

string=$'one\ntwo\nthree' 
IFS=$'\n' read -r -a array <<< "$string" 

я наткнулся на другие посты на этом сайте, которые говорят о либо с помощью mapfile -t или read цикл для чтения файла в массив.

Теперь мой вопрос: Когда я использую IFS=$'\n'?

ответ

3

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

$ IFS=$'\n' read -a arr -d '' <<< $'a b c\nd e f\ng h i' 
$ declare -p arr 
declare -a arr='([0]="a b c" [1]="d e f" [2]="g h i")' 

Но, как вы указали вне, mapfile/readarray это путь, если у вас есть (требуется Bash 4.0 или более поздней версии):

$ mapfile -t arr <<< $'a b c\nd e f\ng h i' 
$ declare -p arr 
declare -a arr='([0]="a b c" [1]="d e f" [2]="g h i")' 

опция -t удаляет символ новой строки из каждого элемента.

Что касается, когда вы хотите использовать IFS=$'\n':

  • Как только что было показано, если вы хотите, чтобы прочитать файлы в массив, одна строка для каждого элемента, если Bash старше 4.0, и вы не хотите использовать петлю
  • Some people promote с использованием IFS без пробелов во избежание неожиданных побочных эффектов от разбиения слов; правильный подход, на мой взгляд, заключается в том, чтобы понять расщепление слов и избегать его при правильном цитировании по желанию.
  • Я видел IFS=$'\n', используемый в сценариях завершения вкладок, например the one for cd in bash-completion: этот скрипт путается с путями и заменяет двоеточия символами новой строки, а затем разбивает их на IFS.
3

Вы немного смущены относительно IFS. МФС является поле Разделитель Внутренний используется Баш преформ софистика на линии разделения в слова после расширения. Значение по умолчанию: [ \t\n] (пробел, табуляция, новая строка).

Переопределяя IFS=$'\n', вы удаляете ' \t' и говорите bash, чтобы разделить слова только на newline символов. (ваше мышление верное). Это приводит к тому, что считывается в один элемент массива без кавычек.

В случае неудачной реализации в вашем read -r -a array < file.Значение -a приводит к тому, что слова в строке назначаются последовательным индексам массива. Тем не менее, вы сказали bash, чтобы разбить только newline (это целая строка). Поскольку вы только вызываете однократное чтение, заполняется только один индекс массива.

Вы можете сделать:

while IFS=$'\n' read -r line; do 
    array+=($line) 
done < "$filename" 

(который вы могли бы сделать без изменения IFS если вы просто процитировал "$line")

Или с помощью IFS=$'\n', вы могли бы сделать

IFS=$'\n' 
array=($(<filename)) 

или, наконец, , вы можете использовать IFS и readarray:

readarray array <filename 

Попробуйте и сообщите мне, если у вас есть вопросы.

+0

Не следует 'array = $ ($ (

+0

Duh - thank you ':)' –

+0

Спасибо вам - Benjamin & David. Ваши ответы очень помогли мне. – learningbee