使用 sed 的行为很奇怪

Very weird behavior using sed

我在编写脚本时遇到了一个大问题:基本上,我从文件中读取了一行。 所有行都由 3 到 8 个连续的字符组成(没有 space)。 然后我使用 sed 来替换模式中的那些行(在我下面的最小脚本中也称为 "var")

var="iao"
for m in `more meshing/junction_names.txt`
do 
    echo $m 
    echo -n $m  | xxd -ps | sed 's/[[:xdigit:]]\{2\}/\x&/g'
    echo $var |sed "s/a/b/"
    echo $var |sed "s/a/$m/"
done

现在这些是我输出的前 3 条记录(反正它们都是一样的)。 我正在使用 linux。根据凯特的说法,所有文件都采用 UTF-8 编码。很奇怪吧?欢迎知道为什么会这样。

J_LEAK 
\x4a\x5f\x4c\x45\x41\x4b\x0d
ibo
oJ_LEAK
JO_1
\x4a\x4f\x5f\x31\x0d
ibo
oJO_1
JPL2_F
\x4a\x50\x4c\x32\x5f\x46\x0d
ibo
oJPL2_F
JF_PL2

您的输入文件包含 DOS 回车 returns(或者可能是用 more 读取它的荒谬尝试引入了它们)。十六进制转储清楚地表明了这一点;每个值都以 \x0d 结尾,它转换为控制代码,使终端将光标跳回行首。

这是一个庞大的常见问题解答,您可以找到许多解决此基本问题的示例,包括 bash tag wiki

切线地,除非您特别要求 shell 对值执行通配符扩展和空格标记化,否则您应该始终引用字符串;并且 Bash 有内置函数来避免不优雅且有点容易出错的 echo | sed。最后,don't read lines with for.

var="iao"
tr -d '5' <meshing/junction_names.txt |
while read -r m; do  # don't use a for loop
    echo "$m"        # quote! 
    echo -n "$m"  | xxd -ps | sed 's/[[:xdigit:]]\{2\}/\x&/g'
    echo "${var/a/b}" # quote; use Bash built-in substitution mechanism
    echo "${var/a/$m}"
done

也许您想一劳永逸地删除回车returns,然后使用while read .... done <fixed-file代替tr管道。