Multiple conditions while using sed

Viewed 87

I would like to ask if it's possible to have multiple conditions checked while using sed.

Basically I have a text file that can contain strings as follows:

a 0000 0000 AA00 0000
a 000000000 AA00 0000
a 0000 0000 BB00 0000
a 0000 0000 CC00 0000
b 0000 0000 AA00 0000
b 0000X0000 BB00 0000
  1. If columns 12-13 contain 'AA|CC' and column 6 is empty, then add 'Z' to column 6.
  2. If columns 12-13 contain 'BB' and column 6 is empty, then add 'ZZ' to column 6.
  3. This applies only to rows starting with 'a'.

Therefore, output should be:

a 0000Z0000 AA00 0000
a 000000000 AA00 0000
a 0000ZZ0000 BB00 0000
a 0000Z0000 CC00 0000
b 0000 0000 AA00 0000
b 0000X0000 BB00 0000

What I have came up with so far is the following.

sed -E '/^a(.{12})A|C/s/^(.{6})[\t ]/\1ZZ/g'

I think I can eventually do this separately, but I can't figure if it's possible in a one liner and I can't figure it out how to use multiple conditions for double chars.

Any help would be greatly appreciated if possible.

3 Answers

A straightforward implementation in GNU sed using extended regular expressions would be:

sed -E '
    /^a.{5} .{5}(AA|CC)/s/(.{6})./\1Z/
    /^a.{5} .{5}BB/s/(.{6})./\1ZZ/
' input.txt

Or, a bit simpler version:

sed -E '
    /^a.{5} .{5}(AA|CC)/s/./Z/7
    /^a.{5} .{5}BB/s/./ZZ/7
' input.txt

Replacing the s/./Z/7 with {s/./Z/7;b} might be slightly more efficient, as suggested by Casimir et Hippolyte in the comments.

Could you please try following, written and tested with shown samples in GNU awk.

awk '
{
  check=substr($0,13,2)
}
/^a/ && (check=="AA" || check=="CC"){
  print substr($0,1,6) "Z" substr($0,8)
  next
}
/^a/ && check=="BB"{
  print substr($0,1,5) "ZZ" substr($0,8)
  next
}
1
'  Input_file

Explanation: Adding detailed explanation for above.

awk '                                               ##Starting awk program from here.
{
  check=substr($0,13,2)                             ##Creating variable check which contains 13t and 14th character of current line.
}
/^a/ && (check=="AA" || check=="CC"){                 ##Checking condition if a line starts from a and check is either equals to AA OR CC then do following.
  print substr($0,1,6) "Z" substr($0,8)             ##Printing sub-string from 1 to 6 characters then Z then rest of the line here.
  next                                              ##next will skip all further statements from here.
}
/^a/ && check=="BB"{                                ##Checking condition if line starts from a AND check is equal to BB then do following.
  print substr($0,1,5) "ZZ" substr($0,8)            ##Printing sub-string from 1 to 5 characters ZZ and rest of line here.
  next                                              ##next will skip all further statements from here.
}
1                                                   ##1 will print current line here.
' Input_file                                        ##Mentioning Input_file name here.

This might work for you (GNU sed):

sed -E 's/^(a.{5})\s(.{5}(AA|CC))/\1Z\2/;s/^(a.{5})\s(.{5}BB)/\1ZZ\2/' file

For lines which begin with a, followed by 5 characters, a space,5 characters then either AA or CC, replace the space by Z.

For lines which begin with a, followed by 5 characters, a space,5 characters then BB, replace the space by ZZ.

Or you may prefer:

sed -E '/^a.{5})\s.{5}(AA|CC)/s/./Z/7;/^a.{5}\s.{5}BB/s/./ZZ/7' file
Related