3

Using sed, how would one insert text after a character that precedes (or follows) some string by N occurrences. As an example, suppose that the line of text to be edited is the following:

command -some -args -c 'a quoted section;some;lines;of code;keyword;more lines;etc();'

After finding this line in a text file (perhaps through the unique string command), I wish to insert text after the second (N=2) semicolon before keyword (i.e., the semicolon separating lines and of). I would specifically like to use sed for the purpose.

Continuing with this example, the expected output would be:

command -some -args -c 'a quoted section;some;lines;INSERTED_STRING;of code;keyword;more lines;etc();'

where INSERTED_STRING; (provided to sed, e.g., via a shell variable) was inserted at the desired position.

1
  • Can you give examples with real inputs and desired outputs? Nov 10, 2017 at 8:58

3 Answers 3

2

I perfer it simple:

sed '/command/s/[^;]*;keyword/INSERTED_STRING;&/'

to insert two fields before the keyword. The general solution would be

sed "/command/s/\([^;]*;\)\{$N\}keyword/INSERTED_STRING;&/"

but note that the N has an offnet of 1 compared to your question: Here, N=2 means to have two fields between the insert and the keyword.

Explanation: /command/ selects only lines with command, so other lines remain untouched. ([^;]*;\) matches one field (a sequence of non-semicolons) including the following semicolon. By following it with \{$N\} the pattern matches $N fields. The following keyword completes this to match keyword and the $N fields before. The replacement pattern consists of the inserted string and &, which gets replaced by everything that was matched (so in the end, it wasn't a replacement, but an insert).

Shorted, and better readable with extended regular expressions:

sed -E "/command/s/([^;]*;){$N}keyword/INSERTED_STRING;&/"
0
2

Using sed, you could change only third occurrence of your pattern which is semicolon here.

sed 's/;/;INSERTED_STRING;/3' <<<"$string"

Edit: To replace Nth occurrence of a string before another specific Pattern String keyword ("relative occurrence", in your case 2nd occurrence) if lines matched with uniqe command string.):

sed -r '/command/ s/([^;]*;){1}keyword/INSERTED_STRING;&/' <<<"$string"
2
  • 2
    1) Surrounding the whole pattern with () and using \1 is not neccessary. You should use & in the replacement instead. 2) Where is N in your answer? What to do for N=42?
    – Philippos
    Nov 10, 2017 at 10:03
  • @Philippos corrected. that's because OP was asked for second and I was stated 2nd in his case so I didn't add unnecessary {1} there. thanks Nov 10, 2017 at 10:11
0

If you see the ;-delimited bits as fields of a record, you could do this with awk like so:

$ awk -F';' -vOFS=';' -vstring="NEW TEXT" '{ $4 = $4 ";" string; print }' file
command -some -args -c 'a quoted section;some;lines;of code;NEW TEXT;keyword;more lines;etc();'

awk would, with -F';', break the line in file down into a number of ;-delimited fields. The code would then modify the fourth such field by appending an extra ; and the string held in the variable string (defined on the command line), and output the data with the modified field. The output would likewise be ;-delimited.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .