shell脚本中的奇怪“回声”行为

时间:2015-04-01 14:59:26

标签: bash echo

我想以这种方式打印我从数组拆分中获得的内容:

string="abc test;ABCtest.it"

IFS=';' read -a array <<< "$string"
name="${array[0]}"
url="${array[1]}"

echo -ne "\n$url,$name" >> "$outputDir/$fileName"

但输出文件不包含URL部分。

我认为问题是.,但我不知道如何修复它。

如果我试试这个

echo $url

它有效!

我也尝试使用printf并使用硬编码的文件名,但没有!

printf '%s %s\n' "$url" "$name"  >> test.txt

似乎当我尝试在变量$url之后连接另一个东西时,变量的某些部分被删除或覆盖到输出文件中。

例如,如果我尝试这个:

printf '%s %s\n' "$url" "pp"  >> test.txt

我用一个简单的cat test.txt获得的是:

 pptest.it

但变量$url的内容必须为ABCTest.it

3 个答案:

答案 0 :(得分:5)

补充chepner's helpful answer

  • 如果输出看起来您希望它看起来像什么,那么它总是值得检查其内容查找隐藏控制字符 ,这可能会改变数据在输出上的外观

  • \r,CR(回车符; ASCII值13)是一个臭名昭着的例子,原因有两个:

    • (正如@chepner所说)它将光标移动到中间字符串的开头,有效地删除了之前的部分内容;例如。:
      • echo $'abcd\refg'打印efgd\r导致所有内容在行开头重新开始打印,只有之前的d < / em> \r幸存,因为恰好是 1个字符。比之后的字符串更长。
        (注意:$'...'语法是所谓的ANSI C-quoted string,允许在\r中使用$'...\r...'之类的转义序列来创建实际控制字符。)
    • 包含意外\r个字符的文件。在与Windows世界接口时经常发生,其中换行符不只是\n字符,而是\r\n序列,并且这些文件在Unix世界中表现得很奇怪。
  • 检查数据的一种简单方法是将其传递给cat -et ,将控制字符突出显示为^<char>个序列:
    • ^M代表\r(CR)
    • ^I代表\t(tab.cchar)
    • ^[代表ESC char。
    • ... # see 'man cat'
    • 一行的结尾表示为$
    • 因此,具有Windows样式行结尾的文件将在^M$输出的行的末尾显示cat -et
  • cat -et应用于上面的示例会产生以下结果,从而可以轻松诊断问题:
    • echo $'abcd\refg' | cat -et # -> 'abcd^Mefg$' - note the ^M
  • dos2unix将Windows样式行结尾(\r\n)转换为Unix行(\r\n的首选工具,但此工具不适用在大多数类Unix平台上预先安装,并且易于使用标准POSIX实用程序来执行此类转换:
    • awk 'sub("\r$", "")+1' win.txt > unix.txt
    • 请注意,此POSIX兼容命令不允许您替换文件就地,但是:
      • 如果您有 GNU sed,则以下内容将执行转换
        • sed -i 's/\r$//' winIn_UnixOut.txt
      • 同时使用 BSD sed(也用于 OSX ),来自bashksh或{{1} }:
        • zsh

答案 1 :(得分:2)

不知何故,$string的值以回车结束。你实际上回应的是

echo -ne "\nABCtest.it\r,abc test"

回车导致光标移动到当前行的开头,然后打印后面的文本,覆盖url。用

删除回车
string=${string#?}

或者首先修复string的设置方式(我怀疑你是从一个使用DOS行结尾的文件中读取的,在这种情况下你可以用dos2unix转换文件。)

答案 2 :(得分:0)

试试这个:

echo -ne "\n""$url"",$name" >> "$outputDir/$fileName"