sed 不会在脚本中扩展我的 BASH 变量

sed 不会在脚本中扩展我的 BASH 变量

我有这个脚本,它将提示输入文件的相对或绝对路径,然后交换空格'''\'它在 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)"

相关内容