![为什么 read -r 会吃掉文本?](https://linux22.com/image/108581/%E4%B8%BA%E4%BB%80%E4%B9%88%20read%20-r%20%E4%BC%9A%E5%90%83%E6%8E%89%E6%96%87%E6%9C%AC%EF%BC%9F%20.png)
我有一个names.txt
文件,其顶行文本是
51 Pipe-line\Closed3\00001011_-_Portfolio\UW\Old\NID50_Future_022814.xlsx
我想写新的文件名替换\
为/
我编写了一个script.sh
并使用调用它sh script.sh
。我的第一次尝试...
while read one two three; do
new=$(echo $two|tr '\\' '/')
echo $one
echo $two
echo $three
echo $new
done < ./names.txt
51
Pipe-lineClosed300001011_-_PortfolioUWOldNID50_Future_022814.xlsx
Pipe-lineClosed300001011_-_PortfolioUWOldNID50_Future_022814.xlsx
这/
把炭吃了。我发现通过了-r
遗嘱显示,/
所以我的下一次尝试是
while read -r one two three; do
new=$(echo $two|tr '\\' '/')
echo $one
echo $two
echo $three
echo $new
done < ./names.txt
51
Pipe-line\Closed3
Pipe-line/Closed3
这会占用文件名的一半。怎么了?我该如何让它发挥作用?
答案1
不是那个read
,而是那个echo
。
我编写了一个
script.sh
并使用调用它sh script.sh
。
在 Debian 和 Ubuntu 中,sh
is dash
,其中echo
计算其参数中的 C 风格反斜杠转义符:
$ dash -c 'foo="foo\000bar"; echo "$foo"; printf "%s\n" "$foo"'
foo
foo\000bar
转换\000
为 NUL 字节,这显然结束了输出的字符串echo
。引用变量在这里没有帮助,因为它只会在命令本身运行之前更改 shell 命令行的处理,而这里是它echo
本身处理反斜杠。
这是一个已知的可移植性问题,此处有更详细的描述:为什么 printf 比 echo 更好?
例如,echo
如果给定参数,Bash 就会进行反斜杠处理-e
。
该问题最初标记为巴什,因此如果您想使用 Bash 运行脚本,请使用 运行bash script.sh
,而不是sh script.sh
。
答案2
这可以使用 sed 以更简单、更可靠的方式完成:
sed -i 's|\\|/|g' myfile
给出:
cat myfile 51 Pipe-line/Closed3/00001011_-_Portfolio/UW/Old/NID50_Future_022814.xls
编辑:
根据您的评论,这就是我实现这一目标的方式:
for i in $(cat test | awk '{print $2}')
do
mv $i `sed 's|\\|/|g' <<< $i`
done
答案3
只需这样就足够了:
tr '\\' / < names.txt