根据该字符串的值,将字符串替换为命令的输出

根据该字符串的值,将字符串替换为命令的输出

我正在 sh 中编写一个脚本:

  • 读取配置文件
  • {{ value_0000 }}对于检索之间的每个值0000
    • 0000使用作为参数传递的值执行命令
    • 替换{{ value_0000 }}输出该命令的

笔记:

  • value_0000总是转换为数字,例如0000
  • 命令总是相同的,例如/bin/command <value>
  • 我不想编辑当前的配置文件,它可以在内存中运行

例子:

# this is a config file
key: {{ value_12345 }}:hello
something
another_key: return:{{ value_56789 }}/yeah

./run.sh

# this is a config file
key: returned-value:hello
something
another_key: return:another-returned-value2/yeah

我可以从配置文件中检索该值,但需要更多代码才能使其按预期工作。

#!/bin/sh
cat some.conf | while read line
do
   echo $line
   val="$(grep -o -P '(?<={{ value_).*(?= }})')"
   command $val
done

答案1

perl

perl -pe 's(\{\{ value_(\d+) \}\})(`cmd $1`)ge' < some.conf

请注意,这里它是安全的,因为$1保证它是非空的,并且不包含 shell 语法中的特殊字符(仅数字),甚至perl在这里绕过 shell。但是,如果您\d+用其他任何内容更改(一个或多个数字的序列),这将变得危险(例如对于诸如 之类的值foo;reboot),您可能需要采取更安全的方法,例如:

perl -pe '
  s(\{\{ value_(.*?) \}\})(
    open my $fh, "-|", "cmd", $1 or die "cannot start cmd: $!";
    local $/ = undef;
    <$fh>;
  )ge' < some.conf

如果cmd接受选项,您可能需要替换"cmd""cmd", "--"or qw(cmd --)(假设它支持--作为选项结束标记)以避免以-( 和可能+) 开头的值出现问题。

任何状况之下,while read最好避免使用 shell 循环来处理文本

答案2

使用 GNU awk 将第三个参数匹配到 match():

$ cat tst.awk
match($0,/(.*{{ value_)([0-9]+)( }}.*)/,a) {
    cmd = "echo \"<foo_" a[2] "_bar>\""
    if ( (cmd | getline output) > 0 ) {
        $0 = a[1] output a[3]
    }
    close(cmd)
}
{ print }

$ awk -f tst.awk some.conf
# this is a config file
key: {{ value_<foo_12345_bar> }}:hello
something
another_key: return:{{ value_<foo_56789_bar> }}/yeah

以及任何 awk:

$ cat tst.awk
match($0,/{{ value_[0-9]+ }}/) {
    cmd = "echo \"<foo_" substr($0,RSTART+9,RLENGTH-12) "_bar>\""
    if ( (cmd | getline output) > 0 ) {
        $0 = substr($0,1,RSTART+8) output substr($0,RSTART+RLENGTH-3)
    }
    close(cmd)
}
{ print }

$ awk -f tst.awk some.conf
# this is a config file
key: {{ value_<foo_12345_bar> }}:hello
something
another_key: return:{{ value_<foo_56789_bar> }}/yeah

相关内容