Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using variables in sed -f (where sed script is in a file rather than inline)

Tags:

sed

We have a process which can use a file containing sed commands to alter piped input.

I need to replace a placeholder in the input with a variable value, e.g. in a single -e type of command I can run;

$ echo "Today is XX" | sed -e "s/XX/$(date +%F)/"
Today is 2012-10-11

However I can only specify the sed aspects in a file (and then point the process at the file), E.g. a file called replacements.sed might contain;

s/XX/Thursday/

So obviously;

$ echo "Today is XX" | sed -f replacements.sed
Today is Thursday

If I want to use an environment variable or shell value, though, I can't find a way to make it expand, e.g. if replacements.txt contains;

s/XX/$(date +%F)/

Then;

$ echo "Today is XX" | sed -f replacements.sed
Today is $(date +%F)

Including double quotes in the text of the file just prints the double quotes.

Does anyone know a way to be able to use variables in a sed file?

like image 840
lazidar Avatar asked Oct 11 '12 01:10

lazidar


People also ask

Does sed work on variable?

The sed command is a common Linux command-line text processing utility. It's pretty convenient to process text files using this command. However, sometimes, the text we want the sed command to process is not in a file. Instead, it can be a literal string or saved in a shell variable.

How do you replace a variable in a file using sed?

How SED Works. In the syntax, you only need to provide a suitable “new string” name that you want to be placed with the “old string”. Of course, the old string name needs to be entered as well. Then, provide the file name in the place of “file_name” from where the old string will be found and replaced.

Does sed write to file?

Sed provides “w” command to write the pattern space data to a new file. Sed creates or truncates the given filename before reads the first input line and it writes all the matches to a file without closing and re-opening the file.


3 Answers

This might work for you (GNU sed):

cat <<\! > replacements.sed
/XX/{s//'"$(date +%F)"'/;s/.*/echo '&'/e}
!
echo "Today is XX" | sed -f replacements.sed

If you don't have GNU sed, try:

cat <<\! > replacements.sed
/XX/{
    s//'"$(date +%F)"'/
    s/.*/echo '&'/
}
!
echo "Today is XX" | sed -f replacements.sed | sh
like image 159
potong Avatar answered Oct 18 '22 03:10

potong


AFAIK, it's not possible. Your best bet will be :

INPUT FILE

aaa
bbb
ccc

SH SCRIPT

#!/bin/sh

STRING="${1//\//\\/}"   # using parameter expansion to prevent / collisions

shift

sed "
s/aaa/$STRING/
" "$@"

COMMAND LINE

./sed.sh "fo/obar" <file path>

OUTPUT

fo/obar
bbb
ccc
like image 24
Gilles Quenot Avatar answered Oct 18 '22 03:10

Gilles Quenot


As others have said, you can't use variables in a sed script, but you might be able to "fake" it using extra leading input that gets added to your hold buffer. For example:

[ghoti@pc ~/tmp]$ cat scr.sed 
1{;h;d;};/^--$/g
[ghoti@pc ~/tmp]$ sed -f scr.sed <(date '+%Y-%m-%d'; printf 'foo\n--\nbar\n')
foo
2012-10-10
bar
[ghoti@pc ~/tmp]$ 

In this example, I'm using process redirection to get input into sed. The "important" data is generated by printf. You could cat a file instead, or run some other program. The "variable" is produced by the date command, and becomes the first line of input to the script.

The sed script takes the first line, puts it in sed's hold buffer, then deletes the line. Then for any subsequent line, if it matches a double dash (our "macro replacement"), it substitutes the contents of the hold buffer. And prints, because that's sed's default action.

Hold buffers (g, G, h, H and x commands) represent "advanced" sed programming. But once you understand how they work, they open up new dimensions of sed fu.

Note: This solution only helps you replace entire lines. Replacing substrings within lines may be possible using the hold buffer, but I can't imagine a way to do it.

(Another note: I'm doing this in FreeBSD, which uses a different sed from what you'll find in Linux. This may work in GNU sed, or it may not; I haven't tested.)

like image 2
ghoti Avatar answered Oct 18 '22 01:10

ghoti