Ubuntu (14 & 16) Bash 来自包含小写 "n" 字符的输入的 printf 循环错误

Ubuntu (14 & 16) Bash errors with printf loops from input containing lowercase "n" characters

我有一些 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

评论中的建议
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

还按照 Michael 的建议将所有变量名称更改为小写,但仍然得到相同的结果。

#!/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

解决方案 谜底已解

感谢大家,但是https://whosebug.com/users/96588/l0b0一语中的。我的脚本中早些时候隐藏了一个 IFS=$'\n'

感谢 Nahuel 和 Charles 的推荐,我现在有了最终的、更好的、更安全的 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

如果它可以包含 %

,则使用 %s 插入带有 printf 的字符串会更安全
printf "\t\"~%s\"\t\t%s\n" "${LINE}" "$ACTION1" >> $OUTPUT

编辑以下评论,在第一个参数中使用单引号,因为没有变量扩展

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

如果内部字段分隔符 ($IFS) 包含字母 n:

,就会发生这种情况
$ IFS=$' \t\nn' read line <<< foon
$ printf '%q\n' "$line"
foo

这是相当常见的 mistake。这是正确的值:

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

示例:

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

解决方案 谜底已解

感谢大家,但是https://whosebug.com/users/96588/l0b0一语中的。我的脚本中早些时候隐藏了一个 IFS=$'\n'

感谢 Nahuel 和 Charles 的建议,我现在有了最终的、更好的和更安全的 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