M J
M J

Reputation: 1

trying to understand sed -need just the line number of a line with specfic text

I'm new to script writing so this may be a 'duh' question, and maybe sed/awk can't do this, I need to insert a user input line of text into a file but it has to be inserted just after a specific, and unique line. The line in question is like "### INSERT NEW INPUT BELOW HERE" I've been using:

sudo sed -i "9i$userinput  from user" ~/filename;

which successfully inserts the user input plus additional text into the file right after the line "### INSERT NEW INPUT BELOW HERE" which happens to be at line 8 so I hard coded 9, but, as it turns out other scripts may add or subtract lines from this file prior to the line "### INSERT NEW INPUT BELOW HERE" which screws me all up... how can I identify the line number of the line with the text "### INSERT NEW INPUT BELOW HERE" and assign it to a variable so that maybe something like:

sudo sed -i "$(linenumber + 1)i$userinput  from user" ~/filename;

might work.
I've tried:

line= "### INSERT NEW INPUT BELOW HERE";
linenum= sed -n '/$line/'= inputfile;
echo linenum;

and

linenum=$(awk 'NR == "$line"' ./inputfile)
echo $linenum;

along with several variations but linenum remains null.

Any help or suggestions?

Upvotes: 0

Views: 57

Answers (4)

repzero
repzero

Reputation: 8412

You can also find and mark the line "### INSERT NEW INPUT BELOW HERE". after words take this line and add a newline character "\n" then append your new line after this newline character.

Command

sed 's/^\(### INSERT NEW INPUT BELOW HERE\).$/\1\n$userinput  from user/g' ~/filename

Upvotes: 0

glenn jackman
glenn jackman

Reputation: 246847

With sed, find the line and append the new line

sed  -i '/### INSERT NEW INPUT BELOW HERE/a your new line here' file

(see https://www.gnu.org/software/sed/manual/sed.html#Other-Commands for the intricacies of multi-line inserts)

Example: add a line of text after "52"

$ text="this is the new stuff"
$ seq 50 55 | sed "/52/a $text"
50
51
52
this is the new stuff
53
54
55

Upvotes: 1

Wintermute
Wintermute

Reputation: 44043

I would match the line directly instead of counting the numbers. Simplest way:

awk -v subst="$userinput from user" '{ print } /### INSERT NEW INPUT BELOW HERE/ { print subst }' filename.txt

Then redirect that to a file and move it back. Or, if you have GNU awk 4.1 or later, use

awk -i inplace -v subst="$userinput from user" '{ print } /### INSERT NEW INPUT BELOW HERE/ { print subst }' filename.txt

to apply the changes in place.

Explanation:

{ print }

This has an implicit "match anything" in the front (technically: "match the empty string", which everything contains), so this prints every line.

/### INSERT NEW INPUT BELOW HERE/ { print subst }

And on lines that match ### INSERT NEW INPUT BELOW HERE (i.e., that contain the string) print the variable subst, that is set to "$userinput from user" with the -v switch. The stuff between the slashes is technically a regex, but since in this case we just have to match a static string, we don't use any of their complicated features.

awk is more robust compared to sed here because sed will throw up if the user inputs something that has meaning for sed (such as backslashes). awk does not have this problem if the -v switch is used.

And if you really just want the number, you can (very similarly) use

linenum=$(awk '/### INSERT NEW INPUT BELOW HERE/ { print NR }' filename.txt)

Upvotes: 1

D3Hunter
D3Hunter

Reputation: 1349

I don't think your script would work. Bash will fail if any spaces around the equal-sign (=) that's used to assign a value to a variable. Also your sed expression is incorrect. Or maybe you just mistyped that in stackoverflow, whatever.

Try this script

line="### INSERT NEW INPUT BELOW HERE";
linenum=`sed -n '/'"$line"'/=;q' inputfile`
echo $linenum;

Upvotes: 1

Related Questions