shellsedzshsingle-quotescommand-substitution

How do I place the output of a command in the search pattern section of sed?


I'm trying to place the output of awk 'NR==4 {split($0, a, "$"); print a[3]}' filename in sed -i 's/1/2/' hyprpaper.conf such that 1 is replaced by the output of the command awk 'NR==4 {split($0, a, "$"); print a[3]}' filename

I've tried sed -i 's/$(awk 'NR==4 {split($0, a, "$"); print a[3]}' hyprpaper.conf)/door/' hyprpaper.conf and variations of it e.g. using backticks instead of $() or placing backticks inside $(), but none of them have worked, all giving me the respective variant of this error message:

zsh: unknown file attribute: b
zsh: no matches found: a[3]} hyprpaper.conf/door/

I await patiently for a solution, thank you.


Solution

  • The main issue in the examples presented in the question is the (mis)use of single quotes ('). The shell does not give any special significance to characters or character sequences delimited by single quotes. You cannot even escape the single quote character itself so as to embed a single quote inside a single quoted region, and the text therein is not processed for any expansions, such as command substitution. It looks like just switching to double-quoted style for the sed expression should do the trick:

    sed -i "s/1/$(awk 'NR==4 {split($0, a, "$"); print a[3]}' hyprpaper.conf)/" hyprpaper.conf
    

    However, that awk command is a bit fraught. Why use split() to split the whole line into fields when that's a core behavior of awk? It would be clearer and more natural to use the -F option to specify your custom field delimiter on the command line:

    sed -i "s/1/$(awk -F '$' 'NR==4 { print $3 }' hyprpaper.conf)/" hyprpaper.conf
    

    If your real 1 is actually something that requires stronger quoting then you could do

    sed -i s/'expression'/"$(awk -F '$' 'NR==4 { print $3 }' hyprpaper.conf)" hyprpaper.conf
    

    , since the shell is perfectly fine with quoting regions of larger strings.