我有这个脚本,它将提示输入文件的相对或绝对路径,然后交换空格''和'\'它在 Linux 控制台中工作。替换是使用第一个完成的sed命令。替换后我回声该路径仅供检查,它是正确的。
然后是第二个sed命令必须处理我为其编写绝对路径的文件。好吧,它不会工作......它看起来像在第二个命令中$drill_file没有扩大。最奇怪的是它在脚本之外扩展得很好......哇!?
#!/bin/bash
echo "Give relative or absolute path to the \"drill.TXT\" file:"
read drill_file_temp
drill_file=$(echo $drill_file_temp | sed -r 's/\s/\\ /g')
echo $drill_file
sed 's/\(^X[[:digit:]]*\)[[:digit:]]\(Y[[:digit:]]*\)[[:digit:]]/\1\2/' $drill_file
echo "Conversion finished."
答案1
您将引用字符放入字符串中。问题是参数扩展后不会解析引用字符。为了获得所需的效果,您需要
eval sed ... $drill_file
您可以使用set -x
查看 shell 如何看待命令行:
> text=a\\\ \\\ \\\ b
> echo $text
a\ \ \ b
> set -x
> : $text
+ : 'a\' '\' '\' b
即 shell 看到的不是一个参数而是四个。
正如其他人所说:您必须引用$drill_file
/ $drill_file_temp
:"$drill_file"
答案2
如果引用变量,则不需要执行第一个 sed:
read -p "Give relative or absolute path to the \"drill.TXT\" file: " drill_file
if [[ -f "$drill_file" ]]; then
sed 's/\(^X[[:digit:]]*\)[[:digit:]]\(Y[[:digit:]]*\)[[:digit:]]/\1\2/' "$drill_file"
echo "Conversion finished."
else
echo "no such file: '$drill_file'"
fi
答案3
内核不理解 \(反斜杠)
如果drill_file
是 'file\ with\ space',则 sed 执行为
sed 's/\(^X[[:digit:]]*\)[[:digit:]]\(Y[[:digit:]]*\)[[:digit:]]/\1\2/' file\ with\ space
.
首先,shell 克隆自身并调用 execl 系列函数之一,传递参数为 argv[0]=sed, argv[1]=s/(^X[[:digit:]])[[:数字:]](Y[[:数字:]])[[:数字:]]/\1\2/、argv[2]=文件\、argv[3]=with\ 和argv[4]=空格。 execl 用 sed 代替 shell。当 sed 开始运行时,它会调用open("file\ ",O_RDONLY)
'with\ ' 和 'space' 并执行相同的操作。内核将请求传递给相关的 fs。 Fs 返回 ENOENT 意味着 fs 中没有这样的条目。确实如此,因为确实不存在这样的文件。 sed 接收错误并显示错误消息。
如果 $drill_file 被引用,sed 得到的文件名是 'file\ with\ space' 并且这次也无法打开。
eval sed 's/\(^X[[:digit:]]*\)[[:digit:]]\(Y[[:digit:]]*\)[[:digit:]]/\1\2/' "$drill_file"
这里 eval 解析它的参数并构建命令并执行构建的命令。它只是多余且令人费解的,你打破并修复。
\(反斜杠)转义仅在 shell 运行时适用。sed 's/\(^X[[:digit:]]*\)[[:digit:]]\(Y[[:digit:]]*\)[[:digit:]]/\1\2/'
”$drill_file_temp“就会成功。
这也有效。
sed 's/\(^X[[:digit:]]*\)[[:digit:]]\(Y[[:digit:]]*\)[[:digit:]]/\1\2/' \
"$(read -p "Give relative or absolute path to the \"drill.TXT\" file: " \
drill_file_temp;echo $drill_file_temp)"