0

So, I was playing around with this answer, when I found that neither

printf_stdin () {
    read input
    printf "$input"
}

sed "/lorem ipsum foobar/ {
   s/'/'\"'\"'/g
   s/\(lorem ipsum \)\(foobar\)/\1'\"\$(printf '%s' '\2' | printf_stdin)\"'/g
   s/.*/printf '%s' '\0'/e
}" <<< "lorem ipsum foobar"

nor

printf_ () {
    printf "$1"
}

sed "/lorem ipsum foobar/ {
   s/'/'\"'\"'/g
   s/\(lorem ipsum \)\(foobar\)/\1'\"\$(printf_ '\2')\"'/g
   s/.*/printf '%s' '\0'/e
}" <<< "lorem ipsum foobar"

works. They both output the error sh: 1: <bash function>: not found. I'm not planning to use this thing anymore, but still, I'm curious why this doesn't work and how to fix it.

Edit

Running

sed "/lorem ipsum foobar/ {
   s/'/'\"'\"'/g
   s/\(lorem ipsum \)\(foobar\)/\1'\"\$(printf '%s' '$0')\"'/g
   s/.*/printf '%s' '\0'/e
}" <<< "lorem ipsum foobar"

gives

lorem ipsum /bin/bash

so sed seems to be invoking the bash shell and not the bourne shell?

3
  • What is your operating system? Is your /bin/sh bash or is it dash? Or something else? Commented 2 days ago
  • If you want to do stuff combining sed, shell, function calls, etc then do yourself a favour and just use perl. It'll be easier, far more capable, faster, and you won't end up getting lost in a maze of twisty little quotation marks. Simple example: echo bar | perl -pe 'BEGIN{sub myfoo {my $str = shift; return "foo $str"}}; s/.*/myfoo $&/e' (sure, this trivial example doesn't need the /e modifier OR a function, but it does illustrate what's possible and how much easier it is than doing it in shell). people try to do too much in shell, a language that makes easy things needlessly difficult. Commented 2 days ago
  • What is your /bin/sh? Is it perhaps a symlink to bash? Does this work if you run export -f printf_stdin before your first command? Commented yesterday

2 Answers 2

2

sed runs shell commands in a sub-shell of the default system shell i.e. whatever /bin/sh links to (Usually a POSIX shell like dash) that shell doesn't support exporting user defined functions (which is needed in this case) i.e. printf_stdin () {...;} is defined in the current running shell (parent) and is called from a subshell (child) where that function isn't available/defined hence sh: 1: <function>: not found... That's why AFAIK.

5
  • Hm I investigated your hypothesis, and it seems that sed runs the subshell $( ... ) as a bash shell? See the appended section titled "Edit", which I just appended. Commented 2 days ago
  • @Grass in your edit $0 is expanded by the shell on the command line before it gets passed to sed so passed as a string ... Try something simple sed 's/.*/printf "%s\n" $0/e' <<<'blabla' instead. Commented 2 days ago
  • Oh I see, thanks! That's pretty interesting. Would it be possible to switch to a bash shell from within the bourne shell? Commented 2 days ago
  • @Grass I don't know if that is practically possible for sed (aside from changing the default system shell which is a bad idea and asking for trouble) ... However, making sed run Bash instead is not enough as the function defined in the parent shell needs to be exported export -f printf_stdin as the latter is the real culprit. Commented 2 days ago
  • I see, thanks! This was interesting. Commented 2 days ago
1

Without the shebang selecting /bin/bash, your system selects /bin/sh, an older, simpler shell, that doesn't understand the bashisms you use.

Before your file's first line,

#!/bin/bash

will tell the system to use bash, rather than sh, to interpret your script.

2
  • Nope. My default shell is bash, plus I ran the above with a bash shebang, as you suggested, before posting my question. The same error is produced. Commented 2 days ago
  • 2
    If you ran your script with a specific shebang then include that in the code in your question so we don't waste time diagnosing issues caused by a missing shebang. Commented 2 days ago

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.