besnico
besnico

Reputation: 271

How to use sed to replace strings in piped input with command outputs using regular expressions

I'm trying to use sed to properly parse the output of auditd records. These have encoded hex, long timestamps and UID/AUID which I need to decode/translate via commands.

I am using pipes as I have to ship this across to the system journal. I have gotten this far:

sed -r "s@msg=([A-Z0-9]*)\$@msg=$(xxd -r -p <<< \1)@"

Sample input:

[IRRELEVANT STUFF] msg=7468697320697320612073616D706C652074657374

The problem is that sed is not "unfolding" the capture group and the nested command receives the wrong argument/input.

xxd should be receiving 7468697320697320612073616D706C652074657374 and not \1

I have tested this in isolated fashion and that is indeed what is happening.

HELP! Thanks!!

Upvotes: 0

Views: 308

Answers (2)

Michael Vehrs
Michael Vehrs

Reputation: 3363

I think you need to do something like this:

sed -r "s/.*msg=([A-Z0-9]*).*/xxd -r -p <<< \1/e" input

Upvotes: 0

Ed Morton
Ed Morton

Reputation: 203597

sed is for doing s/old/new, that is all, for anything else just use awk. With GNU awk for the 3rd arg to match():

awk '
match($0,/(.*msg=)([[:alnum:]]+)$/,a) {
    cmd = "xxd -r -p <<< " a[2]
    $0 = a[1] ((cmd | getline line) > 0 ? line : "ERROR")
    close(cmd)
}
{ print }
'

The above is assuming the syntax for calling your xxd command is exactly what you had in your sed script. I don't have xxd on my system but here's using wc -c instead to show how the script works:

$ wc -c <<< 7468697320697320612073616D706C652074657374
43

$ awk '
match($0,/(.*msg=)([[:alnum:]]+)$/,a) {
    cmd = "wc -c <<< " a[2]
    $0 = a[1] ((cmd | getline line) > 0 ? line : "ERROR")
    close(cmd)
}
{ print }
' file
[IRRELEVANT STUFF] msg=43

Upvotes: 1

Related Questions