1

I have a strings in file:

7017556626 TEST BSAB 20191108 TEST123 3333 1111 BSAB 11
7007760674 TESTCHAS 20191108 TEST123 4444 5555 CHAS 22
7017556626 TEST      20191108 TEST123 3333 1111 CHAS 33
7017556626 TEST SSEQ 20191108 TEST123 2222 7777 BSAB 44
7007760674 TESTCHAS 20191108 TEST123 1111 0000      55

I need to add space before position 16

7017556626 TEST BSAB 20191108 TEST123 3333 1111 BSAB 11
7007760674 TEST CHAS 20191108 TEST123 4444 5555 CHAS 22
7017556626 TEST      20191108 TEST123 3333 1111 CHAS 33
7017556626 TEST SSEQ 20191108 TEST123 2222 7777 BSAB 44
7007760674 TEST CHAS 20191108 TEST123 1111 0000      55

How can I do it?

Freddy
  • 25,565
Tug.s
  • 13

3 Answers3

3

With GNU sed in extended mode:

sed -Ee 's/^(.{15})([^ ])/\1 \2/' file

With GNU sed another method:

sed -e '
   h         ; # hold a copy in case we need it
   s/./\n&/16; # place a marker before the 16-char in the current line
   /\n /g    ; # in case the marker sees a space to its right, revert the changes
   s/\n/ /   ; # in case not then remove the marker
' file

With Perl:

perl -lpe '$_ = "@{[unpack q[A15A*]]}" if index($_," ",15) != 15' file

Results:

7017556626 TEST BSAB 20191108 TEST123 3333 1111 BSAB 11
7007760674 TEST CHAS 20191108 TEST123 4444 5555 CHAS 22
7017556626 TEST      20191108 TEST123 3333 1111 CHAS 33
7017556626 TEST SSEQ 20191108 TEST123 2222 7777 BSAB 44
7007760674 TEST CHAS 20191108 TEST123 1111 0000      55
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
3

Similar to sed, you could use the scriptable editor ed:

printf '%s\n' '1,$s/^\(.\{15\}\)\([^ ]\)/\1 \2/' 'wq' | ed -s file

This sends two newline-separated commands to ed in "silent" mode:

  1. 1,$s/^\(.\{15\}\)\([^ ]\)/\1 \2/ -- on every line (1,$ is the range of line #1 through the last line), perform a search and replace. Search from the beginning of the line (^) for any 15 characters followed by a non-space character; if that's found, group the first 15 characters as subexpression #1 and the non-space character as subexpression #2. Replace that text with subexpression #1, a space,then subexpression #2 -- essentially, put a space after the 15th character if the next one is not a space.
  2. wq -- write the file back to disk and quit ed
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
  • Granted, though after reading https://unix.stackexchange.com/a/119906/117549 I wasn't sure if ed supported it; I should have tested first! – Jeff Schaller Nov 08 '19 at 17:04
  • Ah right. Too bad that answer doesn't mention what those exceptional cases would be :/ And looking at that RE, I started wondering why ed doesn't have the -E option too... – ilkkachu Nov 08 '19 at 17:05
  • @ilkkachu, you could use ex instead which supports fancier regexes. – Wildcard Nov 08 '19 at 20:58
2

With awk:

awk 'substr($0,16,1) != " " { $0=substr($0,0,15)" "substr($0,16) }1' file

If the string at position 16 is not a space character, change the current line to the prefix, space character and suffix. Then print the current line (1).

Freddy
  • 25,565