Возможно, у меня что-то не так, но мне кажется убедительным, что установка IFS в качестве одной из команд в списке pre-do / done абсолютно не влияет.
Внешний IFS (вне while
конструкции) преобладает во всех примерах, показанных в сценарии ниже.
Что тут происходит? Я неправильно понял, что IFS делает в этой ситуации? Я ожидал, что результаты разбиения массива будут такими, как показано в столбце «ожидаемый».
#!/bin/bash
xifs() { echo -n "$(echo -n "$IFS" | xxd -p)"; } # allow for null $IFS
show() { x=($1)
echo -ne " (${#x[@]})\t |"
for ((j=0;j<${#x[@]};j++)); do
echo -n "${x[j]}|"
done
echo -ne "\t"
xifs "$IFS"; echo
}
data="a b c"
echo -e "----- -- -- \t --------\tactual"
echo -e "outside \t IFS \tinside"
echo -e "loop \t Field \tloop"
echo -e "IFS NR NF \t Split \tIFS (actual)"
echo -e "----- -- -- \t --------\t-----"
IFS=$' \t\n'; xifs "$IFS"; echo "$data" | while read; do echo -ne '\t 1'; show "$REPLY"; done
IFS=$' \t\n'; xifs "$IFS"; echo "$data" | while IFS= read; do echo -ne '\t 2'; show "$REPLY"; done
IFS=$' \t\n'; xifs "$IFS"; echo "$data" | while IFS=b read; do echo -ne '\t 3'; show "$REPLY"; done
IFS=" "; xifs "$IFS"; echo "$data" | while read; do echo -ne '\t 4'; show "$REPLY"; done
IFS=" "; xifs "$IFS"; echo "$data" | while IFS= read; do echo -ne '\t 5'; show "$REPLY"; done
IFS=" "; xifs "$IFS"; echo "$data" | while IFS=b read; do echo -ne '\t 6'; show "$REPLY"; done
IFS=; xifs "$IFS"; echo "$data" | while read; do echo -ne '\t 7'; show "$REPLY"; done
IFS=; xifs "$IFS"; echo "$data" | while IFS=" " read; do echo -ne '\t 8'; show "$REPLY"; done
IFS=; xifs "$IFS"; echo "$data" | while IFS=b read; do echo -ne '\t 9'; show "$REPLY"; done
IFS=b; xifs "$IFS"; echo "$data" | while IFS= read; do echo -ne '\t10'; show "$REPLY"; done
IFS=b; xifs "$IFS"; echo "$data" | while IFS=" " read; do echo -ne '\t11'; show "$REPLY"; done
echo -e "----- -- -- \t --------\t-----"
Выход:
----- -- -- -------- actual
outside IFS inside assigned
loop Field loop # inner
IFS NR NF Split IFS # expected IFS
----- -- -- -------- ----- # --------- --------
20090a 1 (3) |a|b|c| 20090a #
20090a 2 (3) |a|b|c| 20090a # |a b c| IFS=
20090a 3 (3) |a|b|c| 20090a # |a | c| IFS=b
20 4 (3) |a|b|c| 20 #
20 5 (3) |a|b|c| 20 # |a b c IFS=
20 6 (3) |a|b|c| 20 # |a | c| IFS=b
7 (1) |a b c| #
8 (1) |a b c| # |a|b|c| IFS=" "
9 (1) |a b c| # |a | c| IFS=b
62 10 (2) |a | c| 62 # |a b c| IFS=
62 11 (2) |a | c| 62 # |a|b|c| IFS=" "
----- -- -- -------- ----- --------- -------
$IFS
, удаляются в начале / конце строки ввода, я полагаю? (a<tab>b
вread var
приведет к тому, что var будет иметь значениеa<space>b
, но если вместо этого у вас будетIFS='<newline>' read var
значение vara<tab>b
.Проще говоря, вы должны читать более чем одну переменную за раз, чтобы
IFS=<something> read ...
конструкция имела видимый эффект в ваших примерах 1 .Вы упускаете сферу действия
read
в примерах. В ваших тестовых примерах нет модификации IFS внутри цикла. Позвольте мне точно указать, где второй IFS влияет на каждую из ваших строк:Это так же, как с любой программой, выполняемой в оболочке. Переменная, которую вы (пере) определяете в командной строке, влияет на выполнение программы. И только это (так как вы не экспортируете). Поэтому, чтобы использовать переопределение
IFS
в такой строке, вам нужно попроситьread
присвоить значения более чем одной переменной . Посмотрите эти примеры:1 Как я только что узнал от Жиля , на самом деле может быть преимущество установки
IFS=''
(пробела) при чтении только одного поля: это позволяет избежать усечения пробела в начале строки.источник
IFS= read
используется вместо простой переустановки переменной среды IFS». Я не знал, что локальные переменные могут быть установлены вызывающей командой. Это был ответ на этот вопрос. Это дало дальнейшее развитие к решению основного вопроса этого вопроса, но к тому времени, когда я понял это, я уже задавал этот вопрос ... Возможно, эти два вопроса похожи на дваsed
вопроса, так что я чувствую, что это так ... Другие названия для Google для Google.