32

I have been told it was possible, but without a single working example, that sed can read from a string variable without need for an input file. I have yet to get it to work. For general safety, I’m writing the $PATH variable to another variable, as I mess with this, because I don’t need other problems to arise until I know exactly how to do this.

Consider the following:

~$x=$PATH
~$sed -i 's/:/ /g' $x

this fails with: No such file or directory.

Here are some others I have tried:

~$ sed -i 's/:/ /g' | (read x) 
sed: no input files
~$ sed -i 's/:/ /g' | (read $x) 
bash: read: `/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games': not a valid identifier
sed: no input files
~$ sed -i 's/:/ /g' | $(read x) 
sed: no input files
~$ sed -i 's/:/ /g' | $(read $x) 
bash: read: `/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games': not a valid identifier
sed: no input files
~$ sed -i 's/:/ /g' < $(read $x) 
bash: read: `/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games': not a valid identifier
bash: $(read $x): ambiguous redirect
~$ sed -i 's/:/ /g' < read $x 
bash: read: No such file or directory
~$ sed -i 's/:/ /g' < (read x) 
bash: syntax error near unexpected token `('
~$ sed -i 's/:/ /g' < $((read x)) 
bash: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games: syntax error: operand expected (error token is "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games")
~$ sed -i 's/:/ /g' < $((read $x)) 
bash: read /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games: division by 0 (error token is "usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games")
~$ sed -i 's/:/ /g' << $((read $x)) 
> ;^C
~$ sed -i 's/:/ /g' << $(read $x)
> ;^C
~$ sed -i 's/:/ /g' $x
sed: can't read /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games: No such file or directory
~$ sed -i 's/:/ /g' < $x
bash: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games: No such file or directory
~$ sed -i 's/:/ /g' < echo $x
bash: echo: No such file or directory
~$ sed -i 's/:/ /g' |  echo $x
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
sed: no input files

Can this even work? I would prefer not to need to write files I don't need just so I can use sed. For this particular example, if ~$x=$PATH ~$sed -i 's/:/ /g' $x actually worked the way I would have hoped, I would get:

/usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin /usr/games /usr/local/games

which I could then assign to a variable, and use in future commands, like ls $x

  • 1
    x=$(echo "$x" | sed 's/:/ /g')? – heemayl Mar 10 '15 at 21:29
19

May be:

~$ x="$PATH"
~$ x="$(echo $x | sed 's/:/ /g')"
~$ echo "$x"
/usr/local/bin /usr/bin /bin /usr/local/games /usr/games
  • @jOh --- notice that sed here is not working on the "string variable" (?), but on the standard input --- which is how it should be. – Rmano Mar 10 '15 at 21:47
  • i think Ill make a feature request to the sed devs – j0h Mar 10 '15 at 22:29
  • 4
    @j0h this has nothing to do with sed, it is a question of how the shell redirects input. sed deals with input streams and it reads them through its standard input. Whether they be files or not is irrelevant. It can accept anything as long as it comes through standard input. – terdon Mar 10 '15 at 22:48
39

This has nothing to do with sed as such, it applies to any program that reads standard input. Anyway, what you were looking for is

sed 's/:/ /g' <<<"$PATH"

There's no reason to save in another variable, nothing you do this way will affect the value stored in the variable. You need the assignment operator (=) for that. The syntax used above is called a "here string" and is specific to bash, ksh and zsh. It serves to pass a variable's value as input to a program that reads from standard input.

I have written up an answer on U&L that lists all the various shell operators like this one. You might want to have a look.

Note that you could also have done

echo "$PATH" | sed 's/:/ /g' 

Finally, you really don't need sed at all for this. You can do the whole thing in bash directly:

echo "${PATH//:/ }"

The above is a bash replacement construct. Given a variable $var, a pattern pat and a replacement (rep), to replace all occurrences of pat with rep, you would do

echo "${var//pat/rep}"

The same thing with a single slash replaces only the first occurrence:

echo "${var/pat/rep}"
  • 2
    Thanks for 'bash replacement construct'. I was able to use: "${1/from/to}" in a Bash function to alter the first argument into subsequent parameters. – AAAfarmclub Nov 14 '17 at 23:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.