Skip to main content
removed confusing and IMO unnecessary level of detail. Sorry Stéphane, but I had trouble even parsing that sentence
Source Link
terdon
  • 252.7k
  • 69
  • 481
  • 719

I don't think sed can do this, but perl can and is only slightly more complex:

echo "a b c syscall=257 success=yes" | perl -pe 's:syscall=(\d+):"SYSCALL=" . `ausyscall $1`:e' 

Although, that will most likely add an extra newline there which you don't want. So you might need this instead:

echo "a b c syscall=257 success=yes" | perl -pe 's:syscall=(\d+):chomp($v=`ausyscall $1`); "SYSCALL=$v" :e' 

Perl's s operator works pretty much the same way as sed's. The only difference here is that by using the e flag at the end (s:old:new:e), that allows us to run perl code in the replacement side, and use the result of the code. The code in question is:

  • `ausyscall $1`: runs sh with ausyscall what-is-captured-by-the-first-pair-or-parens as code to interpret which here, since that's only digits will run ausyscall passing it those digits as an argument ($1 is the equivalent to sed's \1) and that command's output is collected (similar to the `...` shell operator except that trailing newline characters are not stripped and it doesn't choke on NUL bytes like most shells do).

    `ausyscall $1`: run ausyscall passing it $1 (this is the equivalent to sed's \1—although Perl can also work with \1, just not with the e flag—so it's whatever was captured by the first set of parentheses) as an argument. Note that the command is run in the default shell of the system (usually sh).

  • chomp($v=`...`): remove trailing newlines. This removes the newline returned by the ausyscall command. The result is stored in the variable $v.

    chomp($v=`...`): remove trailing newlines. This removes the newline returned by the ausyscall command. The result is stored in the variable $v.

  • "SYSCALL=$v": this returns the desired output.

    "SYSCALL=$v": this returns the desired output.

Note that this is a risky approach. It is fine here, in this specific case, since you are explicitly only capturing numerical digits, but as a general rule, you don't want to execute arbitrary input as a command as that makes you vulnerable to a code injection attack.

I don't think sed can do this, but perl can and is only slightly more complex:

echo "a b c syscall=257 success=yes" | perl -pe 's:syscall=(\d+):"SYSCALL=" . `ausyscall $1`:e' 

Although, that will most likely add an extra newline there which you don't want. So you might need this instead:

echo "a b c syscall=257 success=yes" | perl -pe 's:syscall=(\d+):chomp($v=`ausyscall $1`); "SYSCALL=$v" :e' 

Perl's s operator works pretty much the same way as sed's. The only difference here is that by using the e flag at the end (s:old:new:e), that allows us to run perl code in the replacement side, and use the result of the code. The code in question is:

  • `ausyscall $1`: runs sh with ausyscall what-is-captured-by-the-first-pair-or-parens as code to interpret which here, since that's only digits will run ausyscall passing it those digits as an argument ($1 is the equivalent to sed's \1) and that command's output is collected (similar to the `...` shell operator except that trailing newline characters are not stripped and it doesn't choke on NUL bytes like most shells do).
  • chomp($v=`...`): remove trailing newlines. This removes the newline returned by the ausyscall command. The result is stored in the variable $v.
  • "SYSCALL=$v": this returns the desired output.

I don't think sed can do this, but perl can and is only slightly more complex:

echo "a b c syscall=257 success=yes" | perl -pe 's:syscall=(\d+):"SYSCALL=" . `ausyscall $1`:e' 

Although, that will most likely add an extra newline there which you don't want. So you might need this instead:

echo "a b c syscall=257 success=yes" | perl -pe 's:syscall=(\d+):chomp($v=`ausyscall $1`); "SYSCALL=$v" :e' 

Perl's s operator works pretty much the same way as sed's. The only difference here is that by using the e flag at the end (s:old:new:e), that allows us to run perl code in the replacement side, and use the result of the code. The code in question is:

  • `ausyscall $1`: run ausyscall passing it $1 (this is the equivalent to sed's \1—although Perl can also work with \1, just not with the e flag—so it's whatever was captured by the first set of parentheses) as an argument. Note that the command is run in the default shell of the system (usually sh).

  • chomp($v=`...`): remove trailing newlines. This removes the newline returned by the ausyscall command. The result is stored in the variable $v.

  • "SYSCALL=$v": this returns the desired output.

Note that this is a risky approach. It is fine here, in this specific case, since you are explicitly only capturing numerical digits, but as a general rule, you don't want to execute arbitrary input as a command as that makes you vulnerable to a code injection attack.

make it clear that it runs `sh` and could be dangerous for things other than digits. Remove unnecessary printf .`\1` wouldn't work with the `e` flag here.
Source Link
Stéphane Chazelas
  • 586.6k
  • 96
  • 1.1k
  • 1.7k

I don't think sed can do this, but perl can and is only slightly more complex:

echo "a b c syscall=257 success=yes" | perl -pe 's:syscall=(\d+):"SYSCALL=" . `ausyscall $1`:e' 

Although, that will most likely add an extra newline there which you don't want. So you might need this instead:

echo "a b c syscall=257 success=yes" | perl -pe 's:syscall=(\d+):chomp($v=`ausyscall "$1"`$1`); sprintf "SYSCALL=$v" :e' 

Perl's s operator works pretty much the same way as sed's. The only difference here is that by using the e flag at the end (s:old:new:e), that allows us to run perl code in the replacement side, and use the result of the code. The code in question is:

  • `ausyscall "$1"`$1`: runs sh with ausyscall what-is-captured-by-the-first-pair-or-parens as code to interpret which here, since that's only digits will run ausyscall passing it those digits as an argument ($1 (this is the equivalent to sed's \1, although Perl can also work with) and that command's output is collected (similar to the \1`...` shell operator except that trailing newline characters are not stripped and it doesn't choke on NUL bytes like most shells do) as an argument.
  • chomp($v=`...`): remove trailing newlines. This removes the newline returned by the ausyscall command. The result is stored in the variable $v.
  • sprintf "SYSCALL=$v": this printsreturns the desired output.

I don't think sed can do this, but perl can and is only slightly more complex:

echo "a b c syscall=257 success=yes" | perl -pe 's:syscall=(\d+):"SYSCALL=" . `ausyscall $1`:e' 

Although, that will most likely add an extra newline there which you don't want. So you might need this instead:

echo "a b c syscall=257 success=yes" | perl -pe 's:syscall=(\d+):chomp($v=`ausyscall "$1"`); sprintf "SYSCALL=$v" :e' 

Perl's s operator works pretty much the same way as sed's. The only difference here is that by using the e flag at the end (s:old:new:e), that allows us to run perl code in the replacement side, and use the result of the code. The code in question is:

  • `ausyscall "$1"`: run ausyscall passing it $1 (this is the equivalent to sed's \1, although Perl can also work with \1) as an argument.
  • chomp($v=`...`): remove trailing newlines. This removes the newline returned by the ausyscall command. The result is stored in the variable $v.
  • sprintf "SYSCALL=$v": this prints the desired output.

I don't think sed can do this, but perl can and is only slightly more complex:

echo "a b c syscall=257 success=yes" | perl -pe 's:syscall=(\d+):"SYSCALL=" . `ausyscall $1`:e' 

Although, that will most likely add an extra newline there which you don't want. So you might need this instead:

echo "a b c syscall=257 success=yes" | perl -pe 's:syscall=(\d+):chomp($v=`ausyscall $1`); "SYSCALL=$v" :e' 

Perl's s operator works pretty much the same way as sed's. The only difference here is that by using the e flag at the end (s:old:new:e), that allows us to run perl code in the replacement side, and use the result of the code. The code in question is:

  • `ausyscall $1`: runs sh with ausyscall what-is-captured-by-the-first-pair-or-parens as code to interpret which here, since that's only digits will run ausyscall passing it those digits as an argument ($1 is the equivalent to sed's \1) and that command's output is collected (similar to the `...` shell operator except that trailing newline characters are not stripped and it doesn't choke on NUL bytes like most shells do).
  • chomp($v=`...`): remove trailing newlines. This removes the newline returned by the ausyscall command. The result is stored in the variable $v.
  • "SYSCALL=$v": this returns the desired output.
Rollback to Revision 2
Source Link
terdon
  • 252.7k
  • 69
  • 481
  • 719

I don't think sed can do this, GNU sed I don't think sed can do this, but isn't portable. Perl is though,perl can and it'sis only slightly more complex than simple sed:

echo "a b c syscall=257 success=yes" | perl -pe 's:syscall=(\d+):"SYSCALL=" . `ausyscall $1`:e' 

Although, that will most likely add an extra newline there which you don't want. So you might need this instead:

echo "a b c syscall=257 success=yes" | perl -pe 's:syscall=(\d+):chomp($v=`ausyscall "$1"`); sprintf "SYSCALL=$v" :e' 

Perl's s operator works pretty much the same way as sed's. The only difference here is that by using the e flag at the end (s:old:new:e), that allows us to run perl code in the replacement side, and use the result of the code. The code in question is:

  • `ausyscall "$1"`: run ausyscall passing it $1 (this is the equivalent to sed's \1, although Perl can also work with \1) as an argument.
  • chomp($v=`...`): remove trailing newlines. This removes the newline returned by the ausyscall command. The result is stored in the variable $v.
  • sprintf "SYSCALL=$v": this prints the desired output.

With GNU sed you can use the e flag (from info sed):

‘e’ (command execution) Any characters following the ‘e’ command until the end of the line will be sent to the shell. If whitespace, comments or semicolons are found, they will be included in the shell command, leading to unexpected results: $ echo a | sed '1e touch foo#bar' a $ ls -1 foo#bar 

This means you can do things like this:

$ echo foo | sed 's/f/echo bar/e' baroo 

I don't know much about this though, and only learned of it from the comments to this answer and I can't get it to work for your specific example. As far as I can tell, this should work, but it doesn't:

$ echo "a b c syscall=257 success=yes" | sed -E 's:syscall=([0-9]*):ausyscall \1:e' sh: line 1: a: command not found 

The same thing happens if I store the input string in a file:

$ sed -E 's:syscall=([0-9]*):ausyscall 256:e' file sh: line 1: a: command not found 

For some reason, it seems to be executing the first "word" in its input instead of the command I gave it.

I don't think sed can do this, GNU sed can do this, but isn't portable. Perl is though, and it's only slightly more complex than simple sed:

echo "a b c syscall=257 success=yes" | perl -pe 's:syscall=(\d+):"SYSCALL=" . `ausyscall $1`:e' 

Although, that will most likely add an extra newline there which you don't want. So you might need this instead:

echo "a b c syscall=257 success=yes" | perl -pe 's:syscall=(\d+):chomp($v=`ausyscall "$1"`); sprintf "SYSCALL=$v" :e' 

Perl's s operator works pretty much the same way as sed's. The only difference here is that by using the e flag at the end (s:old:new:e), that allows us to run perl code in the replacement side, and use the result of the code. The code in question is:

  • `ausyscall "$1"`: run ausyscall passing it $1 (this is the equivalent to sed's \1, although Perl can also work with \1) as an argument.
  • chomp($v=`...`): remove trailing newlines. This removes the newline returned by the ausyscall command. The result is stored in the variable $v.
  • sprintf "SYSCALL=$v": this prints the desired output.

With GNU sed you can use the e flag (from info sed):

‘e’ (command execution) Any characters following the ‘e’ command until the end of the line will be sent to the shell. If whitespace, comments or semicolons are found, they will be included in the shell command, leading to unexpected results: $ echo a | sed '1e touch foo#bar' a $ ls -1 foo#bar 

This means you can do things like this:

$ echo foo | sed 's/f/echo bar/e' baroo 

I don't know much about this though, and only learned of it from the comments to this answer and I can't get it to work for your specific example. As far as I can tell, this should work, but it doesn't:

$ echo "a b c syscall=257 success=yes" | sed -E 's:syscall=([0-9]*):ausyscall \1:e' sh: line 1: a: command not found 

The same thing happens if I store the input string in a file:

$ sed -E 's:syscall=([0-9]*):ausyscall 256:e' file sh: line 1: a: command not found 

For some reason, it seems to be executing the first "word" in its input instead of the command I gave it.

I don't think sed can do this, but perl can and is only slightly more complex:

echo "a b c syscall=257 success=yes" | perl -pe 's:syscall=(\d+):"SYSCALL=" . `ausyscall $1`:e' 

Although, that will most likely add an extra newline there which you don't want. So you might need this instead:

echo "a b c syscall=257 success=yes" | perl -pe 's:syscall=(\d+):chomp($v=`ausyscall "$1"`); sprintf "SYSCALL=$v" :e' 

Perl's s operator works pretty much the same way as sed's. The only difference here is that by using the e flag at the end (s:old:new:e), that allows us to run perl code in the replacement side, and use the result of the code. The code in question is:

  • `ausyscall "$1"`: run ausyscall passing it $1 (this is the equivalent to sed's \1, although Perl can also work with \1) as an argument.
  • chomp($v=`...`): remove trailing newlines. This removes the newline returned by the ausyscall command. The result is stored in the variable $v.
  • sprintf "SYSCALL=$v": this prints the desired output.
added 1247 characters in body
Source Link
terdon
  • 252.7k
  • 69
  • 481
  • 719
Loading
deleted 51 characters in body
Source Link
terdon
  • 252.7k
  • 69
  • 481
  • 719
Loading
Source Link
terdon
  • 252.7k
  • 69
  • 481
  • 719
Loading