1

I have a file with below data:

5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|22222222222222222222222222222|ABCD|AB|30
5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|88888888888888888888888888888|ABCD|AB|30
5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|22222222222222222222222222222|ABCD|AB|30
5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|55555555555555555555555555555|ABCD|AB|30

The data is separated with control-A character but I have replaced here with | as I was unable to post data with control-A.

I want to trim 22222222222222222222222222222 value and want first 5 value so our final output data should be like this:

5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|22222|ABCD|AB|30
5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|88888|ABCD|AB|30
5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|22222|ABCD|AB|30
5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|55555|ABCD|AB|30

Looking some help in this.

2

You could do it with awk like so:

awk -F\| 'BEGIN {OFS="|"};{$12=substr($12,1,5)};1' 

-F sets the field separator to |, then before starting to process text we use the BEGIN block to set the output field separator (OFS) to | as well. Then we replace the value in the 12th field with the first 5 characters of that field for each record.

You can give the filename to process as another argument on the command line, which is what you probably want, or use this in a pipeline if you have a process that is generating the file you want to update.

Thanks to Stéphane Chazelas for fixing some issues I had and making it more POSIX-y. In particular, for fixing my start index from 0 to 1. GNU's documentation includes the following line that let me get away with the bug:

If start is less than one, substr() treats it as if it was one.

but 1 is the index of the first character, and so it should be used, especially for people not using gawk. For instance with mawk:

$ mawk 'BEGIN{print substr("1234567", 0, 5)}'
1234
$ mawk 'BEGIN{print substr("1234567", 1, 5)}'
12345
  • 1
    I replaced "|" with "^A" and it is working. – Sandeep Singh Jan 27 '16 at 14:21
  • earlier ($12,1,5)};1 was ($12,0,5)};1 and it also worked. But I am seeing some edition in answer. Can you please explain the change and its impact in detail. – Sandeep Singh Jan 27 '16 at 15:44
  • @SandeepSingh I updated my answer to explain Stéphane Chazelas edit and why my buggy version worked for me (and presumably for you) – Eric Renouf Jan 27 '16 at 15:50
0
sed 's/\([^|]\{0,5\}\)[^|]*/\1/12' <in >out

...or w/ a GNU or BSD sed:

sed -E 's/([^|]{0,5})[^|]*/\1/12' <in >out

5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|22222|ABCD|AB|30
5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|88888|ABCD|AB|30
5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|22222|ABCD|AB|30
5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|55555|ABCD|AB|30

It's pretty simple: of the 12th possible occurrence on an input line of a sequence of any number of not-pipe characters, retain only a maximum of 5.

2

With awk:

awk 'BEGIN{FS=OFS="\1"}; {$12=substr($12,1,5)}; 1' file
  • BEGIN{...}: runs before processing starts
  • FS=OFS="\1": sets the input and output field separator to ^A. According to Wiktionary ^A is the "first character of a message header", whose Octal-value is 1.
  • {$12=substr($12,1,5)}: trims the 12th field.
  • 1: prints (default action) the record.
  • 1
    Won't print if $12 is all zero's which looks like a possibility from OP's example. better to use {$12=substr($12,1,5)}1 just to be safe. – 123 Jan 27 '16 at 14:15
  • 1
    @123, I don't see the behaviour you describe with gawk. I'm guessing the substr forces a string context – iruvar Jan 27 '16 at 14:21
  • 1
    @123 Also with my mawk 1.3.3 i don't see that behaviour. – chaos Jan 27 '16 at 14:23
  • @1_CR substr forces a string context Oh yeah, must do, my bad. – 123 Jan 27 '16 at 14:28

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.