我想用这些字符串上运行的程序的输出替换文本流中的特定字符串。例如,将任何出现的“#filename#”替换为identify filename
有没有简单的方法可以做到这一点?
答案 0 :(得分:3)
假设'identify filename
'本身就是一个命令,那么我认为你需要使用Perl。在最好的Perl难以理解的风格:
while (<>)
{
s/#(\w+)#/my $x = qx%identify $1%; chomp $x; $x/e;
print;
}
这会将一行输入('<>
')读入隐式变量“$_
”;下一行对隐式变量应用替换操作 - 稍后更多细节 - 然后'print
'打印隐式变量。
对于替换操作's///
',第一部分查找散列'#',一系列一个或多个'word'字符 - 字母数字或下划线 - 以及另一个散列,生成标识的文件名称可用作“$1
”。第二部分是替换字符串。在第三个斜杠之后是修饰符'e
',这意味着'执行替换为Perl的位'。而Perl的相关部分是:
my $x = qx%identify $1%; chomp $x; $x
如果散列标记之间的字符串是'filename',则第一部分执行命令'identify filename
',将输出,换行符和全部保存在局部变量$ x中。 “chomp
”操作会删除换行符;最后的'$x
'产生一个值 - 'identify'命令输出的字符串。 (有点令我惊讶的是,Perl不允许更简单的查看:s/#(\w+)#/chomp qx%identify $1%/e
;错误是“Can't modify quoted execution (``, qx) in chomp at xx.pl line 3, near "qx%identify $1%)"
”。)
考虑'识别'命令:
echo "identified file $1 as $PWD/$1"
现在考虑输入行:
abc#def#ghi
输出结果为:
abcidentified file def as /Users/jleffler/tmp/soq/defghi
(运行命令时/Users/jleffler/tmp/soq
恰好是我当前的目录。)
相当不那么难以理解:
while (my $line = <>)
{
if ($line =~ m/#(\w+)#/)
{
my $identity = qx{identify $1};
chomp $identity;
$line =~ s/#\w+#/$identity/;
}
print $line;
}
当然不那么紧凑,但解释非常相似。
请注意,初始版本不是最紧凑的形式。考虑这个版本:
perl -p -e 's/#(\w+)#/my $x = qx%identify $1%; chomp $x; $x/e'
'-p'选项将脚本(参数'-e')置于读,执行,打印循环(REPL)中。
这是Perl的奇迹之一 - TMTOWTDI(发音为'tim-toady') - 有多种方法可以做到。
答案 1 :(得分:0)
REPLACEMENT=`identify filename`
sed "s/#filename#/$REPLACEMENT/g"
编辑:见丹尼斯威廉姆森的评论。