Ubuntu (14 и 16) Ошибки Bash с циклами printf из ввода, содержащего строчные буквы "n"

У меня есть несколько скриптов bash, которые я запускаю в Ubuntu 14.04 и 16.04 уже более года. Некоторое недавнее обновление Ubuntu сломало bash, и я не могу понять, как с этим разобраться.

Пример:

#!/bin/bash
INPUT=myinput.txt
OUTPUT=myoutput.txt
ACTION1="0;"

cat $INPUT | while read LINE
do
printf "\t\"~${LINE}\"\t\t$ACTION1\n" >> $OUTPUT
done

мой скрипт затем перебирает файл, выполняя оператор printf следующим образом, но это вывод

"~jetmo" 0;
"~spamme" 0;
"~baidu" 0;

пример содержимого файла myinput.txt

jetmon
spammen
baidu

Строки ввода, содержащие строчные буквы n, удаляются?? Я пропустил некоторые серьезные изменения в bash, которые произошли, это начало происходить неделю назад и сводит меня с ума сейчас.

Я попытался изменить #!/ Bin/bash на #!/ Bin/sh с теми же результатами.

Также пробовал этот метод зацикливания во входном файле и по-прежнему получать те же результаты.

#!/bin/bash
INPUT=myinput.txt
OUTPUT=myoutput.txt
ACTION1="0;"
while read LINE
do
printf "\t\"~${LINE}\"\t\t$ACTION1\n" >> $OUTPUT
done < $INPUT

Попробовал предложение из комментариев с помощью эха

echo -e -n "\t\"~${LINE}\"\t\t$ACTION1\n" >> $OUTPUT

и теперь я получаю этот вывод

-e -n "~jetmo" 0;
-e -n "~spamme" 0;
-e -n "~baidu" 0;

Запуск hexdump -C myinput.txt дает этот вывод

00000000  6a 65 74 6d 6f 6e 0a 73  70 61 6d 6d 65 6e 0a 62  |jetmon.spammen.b|
00000010  61 69 64 75 0a 0a                                 |aidu..|
00000016

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

#!/bin/bash
input=myinput.txt
output=myoutput.txt
action1="0;"

cat $input | while read line
do
printf "\t\"~${line}\"\t\t$action1\n" >> $output
done

РЕШЕНИЕТайна разгадана

спасибо всем, но l0b0 прибил его по голове. У меня был IFS=$'\n' ранее скрывался в моем сценарии.

Теперь у меня есть последнее, лучшее и безопасное форматирование printf благодаря рекомендациям Науэля и Чарльза, и оно работает на 100% ... не могу вас всех отблагодарить.

#!/bin/bash
input=myinput.txt
output=myoutput.txt
action1="0;"
while IFS= read -r LINE
do
printf '\t"~%s"\t\t%s\n' "${LINE}" "$ACTION1" >> "$output"
done < $input1

3 ответа

Решение

Это может произойти, если внутренний разделитель полей ($IFS) содержит письмо n:

$ IFS=$' \t\nn' read line <<< foon
$ printf '%q\n' "$line"
foo

Это довольно распространенная ошибка. Вот правильное значение:

$ printf '%q\n' "$IFS"
$' \t\n'

Пример:

$ IFS=$' \t\n' read line <<< foon
$ printf '%q\n' "$line"
foon

Безопаснее использовать %s вставить строку с помощью printf, например, если она может содержать %

printf "\t\"~%s\"\t\t%s\n" "${LINE}" "$ACTION1" >> $OUTPUT

РЕДАКТИРОВАТЬ следующие комментарии, с одинарными кавычками в первом аргументе, потому что нет расширения переменной

printf '\t"~%s"\t\t%s\n' "${LINE}" "$ACTION1" >> "$OUTPUT"

РЕШЕНИЕТайна разгадана

спасибо всем, но l0b0 прибил его по голове. У меня был IFS=$'\n' ранее скрывался в моем сценарии.

Теперь у меня есть последнее, лучшее и безопасное форматирование printf благодаря рекомендациям Науэля и Чарльза, и оно работает на 100% ... не могу вас всех отблагодарить.

#!/bin/bash
input=myinput.txt
output=myoutput.txt
action1="0;"
while IFS= read -r LINE
do
printf '\t"~%s"\t\t%s\n' "${LINE}" "$ACTION1" >> "$output"
done < $input1
Другие вопросы по тегам