如何用 sed、awk 等 shell 命令的输出替换子字符串?

Gab*_*iel 5 perl awk sed pattern-matching

我想使用sed或任何命令行工具来通过 shell 命令的输出替换部分行。例如:

  • 通过调用将 linux 纪元替换为人类可读的时间戳date
  • 通过调用内部解码器,将特定协议数据包的十六进制转储替换为其解码后的对应数据包

sed似乎最合适,因为它也允许匹配模式并重新格式化其他内容,例如移动匹配的位,但这不是强制性的。

这是一个简化的示例:

echo "timestamp = 1234567890" | sed "s/timestamp = \(.*\)/timestamp = $(date -u --d @\1 "+%Y-%m-%d %T")/g"
Run Code Online (Sandbox Code Playgroud)

当然,这$(...)件事是行不通的。据我了解,这是针对环境变量的。

那么正确的语法是什么?在这种情况下是否sed推荐?我花了几个小时搜索...sed甚至有能力这样做吗?还有其他更适合的工具吗?

编辑

我需要...

  • 模式匹配。日志中充满了其他内容,因此我需要能够根据上下文(同一行之前和之后的文本)精确定位要替换的字符串。这不包括基于列位置的匹配,例如awk '{$3...
  • 就地替换,以便该行的其余部分“Timestamp =”或其他内容保持不变。这排除了 sed 的 'e' 命令。

fed*_*qui 4

要运行外部命令,sed您需要使用e. 看一个例子:

$ echo "timestamp = 1234567890" | sed "s#timestamp = \(.*\)#date -u --d @\1 "\+\%Y"#e"
2009
Run Code Online (Sandbox Code Playgroud)

完整格式:

$ sed "s#timestamp = \(.*\)#echo timestamp; date -u --d @\1 '\+\%Y-\%m-\%d \%T'#e" <<< "timestamp = 1234567890"
timestamp
2009-02-13 23:31:30
Run Code Online (Sandbox Code Playgroud)

这会捕获时间戳并将其转换为+%Y格式。

man sed

e

该命令允许将 shell 命令的输入通过管道传送到模式空间。如果进行了替换,则执行在模式空间中找到的命令,并用其输出替换模式空间。尾随换行符被抑制;如果要执行的命令包含 null 字符,则结果未定义。这是一个 GNU sed 扩展。


不过,你看它有点“丑”。根据你想要做什么,你最好使用常规while循环来获取值,然后date正常使用。例如,如果文件如下:

timestamp = 1234567890
Run Code Online (Sandbox Code Playgroud)

然后你可以说:

while IFS="=" read -r a b
do
  echo "$b"
done < file
Run Code Online (Sandbox Code Playgroud)

这将使您拥有$b时间戳,然后您可以执行date ....

  • 问题是,整行都被命令的输出替换。我只想替换时间戳(或用其解码值替换十六进制),就像 sed 通常所做的那样。 (2认同)