我正在尝试通过 修改存储在变量 ( $var
)中的路径sed
。事实上,$(dirname "$var")
由于与脚本用途相关的原因,我需要进行替换。
的一个示例var
是var=/dir/dir xyz/file.txt
, whilefilename
包含多个要替换的路径,这些路径可以位于任何位置(一次位于行的中间附近,另一条位于行首,等等)。下面我尝试举一个例子filename
:
dog foo/bar /dir/dir xyz/file.txt
a b c d /dir/dir xyz/file.txt x y z
/dir/dir xyz/file.txt 1234
{[(/dir/dir xyz/file.txt
我想要的是
dog foo/bar .
a b c d . x y z
. 1234
{[(.
我尝试了以下方法
sed "s|"$(dirname "$var")"|.|g" "$filename"
获得sed: -e expression #1, char 31: unterminated `s' command
你可以帮帮我吗?当然,除了 之外,您还可以建议其他方式sed
。
答案1
在:
sed "s|"$(dirname "$var")"|.|g" "$filename"
和被引用,但 不在s|
引号内,因此受到 split+glob 的影响。|.|g
$(dirname "$var")
sed -e "s|$(dirname -- "$var")|.|g" -- "$filename"
会修复这个问题(也添加缺少的s),但这仍然是错误的,因为in--
的左侧被解释为正则表达式(更不用说如果包含字符,您可能会遇到严重的问题;并且适用于文本,而不保证文件名是)。s/lhs/rhs/flags
sed
$var
|
sed
例如,.
匹配任何字符,而不仅仅是.
。
你应该这样做:
DIR="$(dirname -- "$var")" perl -pe 's/\Q$ENV{DIR}\E/./g' < "$filename"
以便可以使用任意文件路径。
严格来说,对于任意文件路径,包括包含换行符的文件路径,我们需要添加选项-0777
(slurp 模式),perl
并且不能使用删除尾随换行符的命令替换。这可以通过将完整的内容传递$var
给perl
并使用 perl dirname()
(来自File::Basename
模块)来完成。
答案2
这似乎是您想要做的所有事情,使用任何 sed 并假设您的变量不包含任何:
s:
$ var='/dir/dir xyz/file.txt'
$ sed "s:$var:.:" file
dog foo/bar .
a b c d . x y z
. 1234
{[(.
我不知道你为什么打电话来dirname
。另外,如果您不打算将我们/
作为 sed 分隔符,请不要使用像这样的正则表达式元字符,|
因为这最多只会混淆您的代码,请选择一个像:
始终是文字的字符。并且不要对非环境变量使用全大写的变量名称,请参阅正确的 bash 和 shell 脚本变量大写。
给定你的评论dirname
,如果您确实因某种原因需要打电话,那么您可以这样做:
$ sed "s:$(dirname "$var"):.:" file
dog foo/bar ./file.txt
a b c d ./file.txt x y z
./file.txt 1234
{[(./file.txt