0

I have a fixed width file with the below format

012019-06-03070005000799111160300000030XXXXXXX0700000000030  
012019-06-03070005000799165030700000030XXXXXXX0700000000030  
012019-06-03070005000799175500700000030XXXXXXX0700000000030  
022019-06-030007276384I06000000000000207000991755007000000300  
022019-06-030007276384I06000000000000107000991755007000000300  
012019-06-03070005000799175840700000030XXXXXXX0700000000030  
022019-06-030007276384I06000000000000407000991758407000000300  
022019-06-030007276384I06000000000000307000991758407000000300  
012019-06-03070005000799194080700000030XXXXXXX0700000000030  
012019-06-03070005000790035750700000030XXXXXXX0700000000030  
012019-06-03070005000790036660700000030XXXXXXX0700000000030 

I need work on the lines starting with 02 and have to replace the characters from 20th position to 50th position with "MMMM" preserving the spaces till the 50th position.

My output should look like this

012019-06-03070005000MMMM                          00000030
012019-06-03070005000MMMM                          00000030
012019-06-03070005000MMMM                          00000030
022019-06-03000727638MMMM                          70000003
022019-06-03000727638MMMM                          70000003
012019-06-03070005000MMMM                          00000030
022019-06-03000727638MMMM                          70000003
022019-06-03000727638MMMM                          70000003
012019-06-03070005000MMMM                          00000030
012019-06-03070005000MMMM                          00000030
012019-06-03070005000MMMM                          00000030

I tried sed -Ee '/^02"s/((.20).{30}/\1$(printf "%-30s" MMMM)/"', which replaces on the records starting with 01 and 02 both, but I want to work on records starting with 02.

  • You didn't try that, this is no valid code. The closing slash is missing after /^01, the double (( seems wrong, at least it needs to get closed somewhere, and your qutoting won't work (the single quotes prevent expansion and keep the literal double quotes. Did you mean sed -E "/^02/s/(.20).{30}/\1$(printf "%-30s" MMMM)/"? But this really works on only 02 lines. – Philippos Jul 18 '19 at 6:23
1

Try this,

Option 1: As per your desired output

sed "s/\(.\{21\}\)\(.\{30\}\)\(.\{8\}\)\(.*\)/\1$(printf "%-30s" MMMM)\3/"  file
012019-06-03070005000MMMM                          00000030
012019-06-03070005000MMMM                          00000030
012019-06-03070005000MMMM                          00000030
022019-06-03000727638MMMM                          70000003
022019-06-03000727638MMMM                          70000003
012019-06-03070005000MMMM                          00000030
022019-06-03000727638MMMM                          70000003
022019-06-03000727638MMMM                          70000003
012019-06-03070005000MMMM                          00000030
012019-06-03070005000MMMM                          00000030
012019-06-03070005000MMMM                          00000030
  • (.\{21\}\) first 21 characters will be stored in \1
  • (.\{30\}\) next 30 charecters will be stored in \2
  • (.\{8\}\) next 8 charecters will be stored in \3
  • (.*\) remaining stored in \4
  • Then we will substitute \1\2\3\4 with \1$(printf "%-30s" MMMM)\3

Option 2: As per your context

sed "/^02/ s/\(.\{19\}\)\(.\{31\}\)\(.*\)/\1$(printf "%-30s" MMMM)\3/" file
012019-06-03070005000799111160300000030XXXXXXX0700000000030  
012019-06-03070005000799165030700000030XXXXXXX0700000000030  
012019-06-03070005000799175500700000030XXXXXXX0700000000030  
022019-06-030007276MMMM                          07000000300  
022019-06-030007276MMMM                          07000000300  
012019-06-03070005000799175840700000030XXXXXXX0700000000030  
022019-06-030007276MMMM                          07000000300  
022019-06-030007276MMMM                          07000000300  
012019-06-03070005000799194080700000030XXXXXXX0700000000030  
012019-06-03070005000790035750700000030XXXXXXX0700000000030  
012019-06-03070005000790036660700000030XXXXXXX0700000000030
  • /^02/ will do the replacement only if the line starts with "02"
  • (.\{19\}\) first 19 characters will be stored in \1
  • (.\{31\}\) next 31 characters will be stored in \2
  • (.*\) remaining stored in \3
  • Then it will substitute \1\2\3 with \1$(printf "%-30s" MMMM)\3
| improve this answer | |
  • Difficult to read for me. You don't need \2 and \4, so why don't you leave the braves there: sed "s/\(.\{21\}\).\{30\}\(.\{8\}\).*/\1$(printf "%-30s" MMMM)\2/". Also, in this case I would suggest extended regular expressions for readability: sed -E "s/(.{21}).{30}(.{8}).*/\1$(printf "%-30s" MMMM)\2/" – Philippos Jul 18 '19 at 6:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.