Bash在匹配组上查找/替换并运行命令

时间:2014-12-09 23:26:27

标签: bash awk sed

我尝试进行动态查找/替换,其中来自find的匹配组在替换中被操作。

testfile的:

…
other text
base64_encode_SOMEPATH_ something
other(stuff)
text base64_encode_SOMEOTHERPATH_
…

这样的事情:

sed -i "" -e "s/(base64_encode_(.*)_)/cat MATCH | base64/g" testfile

会输出类似的内容:

…
other text
U09NRVNUUklORwo= something
other(stuff)
text U09NRU9USEVSU1RSSU5HCg==
…

2 个答案:

答案 0 :(得分:2)

awk '!/^base64_encode_/ { print } /^base64_encode_/ { fflush(); /^base64_encode_/ { fflush(); sub("^base64_encode_", ""); sub("_$", ""); cmd = "base64" ; print $0 | cmd; close(cmd); }' testfile > testfile.out

这表示不加改变地打印不匹配的行。

使用awk函数sub()更改匹配行以提取要编码的字符串,然后将其传送到base64命令,该命令将结果打印到stdout。

需要fflush调用,以便在awk输出出现之前刷新base64的所有先前输出,确保不重新排序行。

修改

正如评论中所指出的,测试每一行两次以匹配一个模式并且不匹配相同的模式并不是很好。这个单一动作处理所有行:

{
  if ($0 !~ "base64_encode_")
  {
    print;
    next;
  }
  fflush();
  sub("^.*base64_encode_", "");
  sub("_$", "");
  cmd = "base64";
  print $0 | cmd;
  close(cmd);
}

答案 1 :(得分:2)

根据您的新要求更新。现在使用GNU awk为第3个arg匹配()以方便:

$ awk 'match($0,/(.*)base64_encode_([^_]+)_(.*)/,arr) {
      cmd = "base64 <<<" arr[2]
      if ( (cmd | getline rslt) > 0) {
          $0 = arr[1] rslt arr[3]
      }
      close(cmd)
  } 1' file
…
other text
U09NRVNUUklORwo= something
other(stuff)
text U09NRU9USEVSU1RSSU5HCg==
…

如果您要使用getline,请务必阅读并理解http://awk.info/?tip/getline

如果你不能安装GNU awk(但是你真的,真的会因为尝试这样做而受益)那么这样的东西可以用于任何现代的awk:

$ awk 'match($0,/base64_encode_[^_]+_/) {
      arr[1] = substr($0,1,RSTART-1)
      arr[2] = arr[3] = substr($0,RSTART+length("base64_encode_"))
      sub(/_.*$/,"",arr[2])
      sub(/^[^_]+_/,"",arr[3])

      cmd = "base64 <<<" arr[2]
      if ( (cmd | getline rslt) > 0) {
          $0 = arr[1] rslt arr[3]
      }
      close(cmd)
  } 1' file

我说“类似”,因为你可能需要调整substr()和/或sub()args如果它们稍微关闭,我还没有测试过。