0

I'm trying to figure out how to use sed (I realise I could use other tools but I'd like to know how to do it in sed, if it really makes more sense in another tool please advise) to edit a file containing lines like this:

1234561234567809912345612345678    00000999988STRING ONE        EX30 0600000001 K XXYY
1122331122334409922334466554433    00000123499STRING TWO        EX99 0600000002 K XXYY

as well as a number of other lines which are of different formats.

the strings STRING ONE and STRING TWO are in positions 47-64 (including their following spaces).

I want to change text in positions 65-80 to another value dependant on the contents of positions 47-64.

So for the STRING ONE line, chars 65-80 would be amended to "AAAABBBBCCCC " (4 trailing spaces).

In the STRING TWO line, chars 65-80 would be amended to "XXXYYYZZZ " (4 trailing spaces).

I've got this far:

sed 's/^\(.\{64\}\)EX/\1234567890 /'

which will substitute "EX" at char 65 to "234567890 " but this

  • doesn't account for picking the correct lines (with STRING ONE or STRING TWO)
  • only substitutes "EX"

& there are other things I'm not following here.

  • Why the dot between the open bracket & the backslash curly bracket?
  • why precede the 1 with a backslash (which seems to be necessary but causes the 1 not to be in the substitute string)?

I expect I could get this done using grep & manipulating output to temporary files or environment variables but would be nice to know if I can do it more elegantly.

1 Answer 1

0

. in a pattern means "any character". .\{64\} means "64 characters", any of them.

\1 is a back reference to the first matching group, i.e. what was matched by the first pair of \(...\) parentheses. To insert a literal 1, don't prepend the backslash.

You can use "addresses" in sed to restrict a command only to some lines, e.g.

sed '/^.\{46\}STRING ONE \{8\}/s/^\(.\{64\}\).\{16\}/\1AAAABBBBCCCC    /'

which reads If the line starts with 46 characters followed by STRING ONE and 8 spaces, remember the first 64 characters in \1, and replace them and the following 16 characters by the remembered characters followed by AAAABBBBCCCC and four spaces.

To add more commands with addresses, separate them with semicolons or use multiple -e switches:

sed -e '/address1/s/pattern1/replacement1/;/address2/s/pattern2/replacement2/'
sed -e '/address1/s/pattern1/replacement1/' -e '/address2/s/pattern2/replacement2/'
1
  • great thanks choroba. Solved my problem & explained it clearly.
    – Chris
    Dec 2, 2016 at 16:47

You must log in to answer this question.

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