5

我们有一个进程可以使用包含sed命令的文件来更改管道输入。

我需要用变量值替换输入中的占位符,例如在-e我可以运行的单一类型的命令中;

$ echo "Today is XX" | sed -e "s/XX/$(date +%F)/"
Today is 2012-10-11

但是我只能指定sed文件中的方面(然后将进程指向文件),例如一个名为的文件replacements.sed可能包含;

s/XX/Thursday/

很明显;

$ echo "Today is XX" | sed -f replacements.sed
Today is Thursday

但是,如果我想使用环境变量或 shell 值,我找不到使其扩展的方法,例如 if replacements.txtcontains;

s/XX/$(date +%F)/

然后;

$ echo "Today is XX" | sed -f replacements.sed
Today is $(date +%F)

在文件文本中包含双引号只会打印双引号。

有谁知道一种能够在sed文件中使用变量的方法?

4

5 回答 5

7

这可能对您有用(GNU sed):

cat <<\! > replacements.sed
/XX/{s//'"$(date +%F)"'/;s/.*/echo '&'/e}
!
echo "Today is XX" | sed -f replacements.sed

如果您没有 GNU sed,请尝试:

cat <<\! > replacements.sed
/XX/{
    s//'"$(date +%F)"'/
    s/.*/echo '&'/
}
!
echo "Today is XX" | sed -f replacements.sed | sh
于 2012-10-11T05:55:31.557 回答
3

AFAIK,这是不可能的。您最好的选择是:

输入文件

aaa
bbb
ccc

SH脚本

#!/bin/sh

STRING="${1//\//\\/}"   # using parameter expansion to prevent / collisions

shift

sed "
s/aaa/$STRING/
" "$@"

命令行

./sed.sh "fo/obar" <file path>

输出

fo/obar
bbb
ccc
于 2012-10-11T01:48:27.973 回答
2

正如其他人所说,您不能在 sed 脚本中使用变量,但您可以使用添加到您的保持缓冲区的额外前导输入来“伪造”它。例如:

[ghoti@pc ~/tmp]$ cat scr.sed 
1{;h;d;};/^--$/g
[ghoti@pc ~/tmp]$ sed -f scr.sed <(date '+%Y-%m-%d'; printf 'foo\n--\nbar\n')
foo
2012-10-10
bar
[ghoti@pc ~/tmp]$ 

在此示例中,我使用进程重定向来获取 sed 的输入。“重要”数据由 生成printf。您可以改为 cat 文件,或运行其他程序。“变量”由date命令生成,并成为脚本的第一行输入。

sed 脚本获取第一行,将其放入 sed 的保持缓冲区,然后删除该行。然后对于任何后续行,如果它匹配双破折号(我们的“宏替换”),它将替换保持缓冲区的内容。并打印,因为这是 sed 的默认操作。

保持缓冲区(g、G、h、H 和 x 命令)代表“高级”sed 编程。但是,一旦您了解了它们的工作原理,它们就会打开 sed fu 的新维度。

注意:此解决方案仅帮助您替换整行。使用保持缓冲区可以替换行内的子字符串,但我无法想象一种方法。

(另一个注意事项:我在 FreeBSD 中执行此操作,它使用的 sed 与您在 Linux 中找到的不同。这可能在 GNU sed 中有效,也可能无效;我没有测试过。)

于 2012-10-11T02:55:08.593 回答
0

我同意斯普特尼克的观点。我不相信 sed 能够完成这项任务。

但是,您可以即时生成该文件。

您可以将日期更改为固定字符串,例如 __DAYOFWEEK__.

创建一个临时文件,使用 sed 替换__DAYOFWEEK__$(date +%Y).

然后用 . 解析你的文件sed -f $TEMPFILE

sed 很棒,但可能是时候使用 perl 之类的东西来即时生成日期了。

于 2012-10-11T02:02:02.850 回答
0

要使用 sed 文件在替换表达式中添加换行符,最终对我有用的是转义文字换行符。示例:在字符串 NewLineHere 之后附加一个换行符,那么这对我有用:

#! /usr/bin/sed -f
s/NewLineHere/NewLineHere\
/g

不确定这是否重要,但我在 Solaris unix 上,所以肯定不是 GNU sed。

于 2019-08-06T14:01:18.437 回答