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==
…
source to share
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.
source to share
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);
}
source to share