bash脚本中字符串的串联充当替换模式

时间:2017-05-14 11:01:27

标签: arrays linux string bash concatenation

我需要将文件读入数组并在每行的末尾连接一个字符串。这是我的bash脚本:

#!/bin/bash

IFS=$'\n' read -d '' -r -a lines < ./file.list
for i in "${lines[@]}"
do
    tmp="$i"
    tmp="${tmp}stuff"
    echo "$tmp"
done

但是,当我执行此操作时,会发生replace的操作,而不是连接。

例如,在file.list中,我们有:

http://www.example1.com
http://www.example2.com

我需要的是:

http://www.example1.comstuff
http://www.example2.comstuff

但是在执行上面的脚本后,我在终端上得到如下内容:

stuff//www.example1.com
stuff//www.example2.com
不过,我的电脑是Mac OS。

3 个答案:

答案 0 :(得分:4)

文件./file.lst很可能是在Windows系统上生成的,或者至少是使用Windows约定保存为行尾。

Windows使用两个字符的序列来标记文本文件中的行尾。这些字符为CR\r),后跟LF\n)。类Unix系统(从版本10开始的Linux和macOS)使用LF作为行尾字符。

代码中IFS=$'\n'前面的作业read告诉read使用LF作为行分隔符。 read不会将LF字符存储在其生成的数组中(lines[]),但lines[]中的每个条目都以CR字符结尾。< / p>

tmp="${tmp}stuff"执行它应该做的事情,即它将单词stuff附加到变量tmp的内容(从文件读取的行)。

从输入文件读取的第一行包含字符串http://www.example1.com,后跟CR字符。附加字符串stuff后,变量tmp的内容为:

http://www.example1.com$'\r'stuff

CR字符无法打印。它在终端上打印时有一个特殊的解释:它在行的开头(第1列)发送光标而不改变行。

echo打印上面的行时,它会打印(从新行开始)http://www.example1.com,然后是CR字符,它将光标发送回行的开头。打印字符串stuffstuff片段会覆盖已在该行(http:)上打印的前5个字符,并且结果(因为它在屏幕上可见)为:

stuff//www.example1.com

解决方案是从输入文件中删除CR个字符。有几种方法可以实现这一目标。

从输入文件中删除CR字符的一种简单方法是使用命令:

sed -i.bak s/$'\r'//g file.list

它会从文件CR的内容中删除所有file.list个字符,将更新后的字符串保存回file.list文件,并将原始file.list文件存储为{{ 1}}(备份副本,以防它没有产生您期望的输出)。

摆脱file.list.bak字符的另一种方法是让shell在附加CR的命令中将其删除:

stuff

tmp="${tmp/$'\r'/}stuff" 之类的构造中展开变量时,${tmp/a/b}a的所有外观都会被$tmp替换。在这种情况下,我们无需替换b

答案 1 :(得分:2)

我猜它与Carriage Return字符有关。 您的file.list是否在Windows上创建了?如果是这样,请在运行脚本之前尝试使用dos2unix

修改

您可以使用file命令检查文件。

示例:

file file.list

如果您在Windows记事本中保存文件,请执行以下操作:

enter image description here

然后它可能会出现这样:

  • file.list: ASCII text, with no line terminators 

您可以使用iconv之类的内置工具来转换编码。但是,对于这样的简单用法,您只需使用适用于多种编码的命令,无需任何转换。

您可以简单地通过cat缓冲文件,并使用适用于以下任一项的正则表达式:

  • 回车后跟行终止符,或
  • 线路终结器就在它自己的

然后追加字符串。

示例:

cat file.list | grep -E -v "^$" | sed -E -e "s/(\r?$)/stuff/g" 

将使用ASCII文本和没有行终止符的ASCII文本。

答案 2 :(得分:0)

如果您需要修改流以附加固定字符串,则可以使用sedawk,例如:

sed 's/$/stuff/'

将东西附加到每行的末尾。