Bash find / replace and run command in match group

I am trying to do a dynamic search / replace when the matching group from find is processed in replace.

TestFile:


other text
base64_encode_SOMEPATH_ something
other(stuff)
text base64_encode_SOMEOTHERPATH_


      

Something like that:

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

      

To output something like:


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


      

+3


source to share


2 answers


Updated as per your new requirement. Now using GNU awk for 3rd argument to match () for convenience:

$ 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==


      

Make sure you read and understand http://awk.info/?tip/getline if you intend to use getline

.



If you can't install GNU awk (but you really, REALLY would benefit from trying like this), then something like this will work with any modern 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

      

I say "something like" because you might need to tweak the args substr () and / or sub () if they are slightly off, I haven't tested it.

+2


source


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

      

This suggests that the print inconsistent lines are not changed.

The corresponding lines are modified with a function awk

sub()

to extract the line to be encoded, which is then passed to a command base64

that prints the result to standard output.

The call is fflush

required so that all previous output from is awk

flushed before exiting base64

, so that lines are not redirected.



Edit

As pointed out in the comment, testing each line twice for pattern matching and not matching the same pattern is not good. This one action processes all lines:

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

      

+2


source







All Articles