1

I need to copy one of the header columns in a fixed width file and create a new field in detail record then paste the field in that placeholder.

Note : There are multiple header and detail records in a file and sample file data with expected output as follows.

Record type : H- Header , D- Detail.

Input:

H0003A

D0001A

D0002A

D0003A

H0007A

D0001A

D0002A

D0003A

D0004A

D0005A

D0006A

D0007A

H0002B

D0001B

D0002B

H0004A

D0001A

D0002A

D0003A

D0004A

Expected output:

H0003A

D0001A3

D0002A3

D0003A3

H0007A

D0001A7

D0002A7

D0003A7

D0004A7

D0005A7

D0006A7

D0007A7

H0002B

D0001B2

D0002B2

H0004A

D0001A4

D0002A4

D0003A4

D0004A4

3 Answers 3

2

So apparently you want to add the 5th character of each header line to the end of each non-header line. In Awk:

awk 'BEGIN{OFS=FS=""} /^H/ {x = $5} /^D/ {$(NF+1) = x} 1'

or (slightly more typing, but avoids regular expression comparison)

awk 'BEGIN{OFS=FS=""} $1=="H" {x = $5} $1=="D" {$(NF+1) = x} 1'

Similarly in Perl:

perl -F'' -ple '$_ .= $x if $F[0] eq "D"; $x = $F[4] if $F[0] eq "H"'

For the willfully perverse

sed -e '/^H/ {p;s/.$//;h;d;}' -e '/^D/ {G;s/\n....//;}'
5
  • Thanks it works. Also I tried to get the range of characters based on position numbers. But it didnt work as expected. In Awk: awk 'BEGIN{OFS=FS=""} $1=="H" {x = $(cut -c 2-5)} $1!="H" {$(NF+1) = x} 1' It copies entire header record column to detail record. I am trying to modify slightly and it seems cut command is not working and my expectation is to extract the substring of Second to Fifth position of values and paste to Detail records. Output I got : H0003A D0001AH0003A D0002AH0003A D0003AH0003A Output which I expected is: H0003A D0001A0003 D0002A0003 D0003A0003
    – Chakkara
    Jun 30, 2018 at 19:41
  • @Chakkara you can't use the external cut command from awk in that way; however you can use awk's own substr function e.g. awk -F '' '$1=="H" {x = substr($0,2,4)} $1=="D" {$0 = $0 x} 1' Jun 30, 2018 at 19:55
  • Thanks for the command. For the below input I am not getting the record count in detail columns. I modified command accordingly based on data but not working as expected. Kindly advise in this scenario where it was wrong. awk -F '' '$1=="H" {x= substr($0,18,4)} $1!="H" {$0=$0 x} 1' 12 H 0003A 12305245D 2500 12345 5454 87870001A 12305245D 2500 12345 5454 87870002A 12305245D 2500 12345 5454 87870003A
    – Chakkara
    Jul 2, 2018 at 7:50
  • @Chakkara the comments section is not the place for follow-on questions - if you have different requirements or different data (your original data doesn't have 18 characters) then please edit your question accordingly - or post another if your requirements are substantially different. Jul 2, 2018 at 12:24
  • Yes. I have posted this query separately.Kindly check in below link unix.stackexchange.com/questions/452993/…
    – Chakkara
    Jul 2, 2018 at 12:33
0

Bash should generally not be used as a text processor but this should accomplish your task if no better solutions are posted:

#!/bin/bash

input=/path/to/input
output=/path/to/output

while read -r record; do
    if [[ "${record:0:1}" == 'H' ]]; then
        x=$(awk -vr=${record//[[:alpha:]]/} 'BEGIN{print r / 1}')
        echo "$record"
    elif [[ -z "$record" ]]; then
        echo
    else
        echo "${record}${x}"
    fi
done <"$input" >"$output"

This will read through your input line by line. If the record starts with H it will grab the number and divide it by 1 (to remove the leading zeros) and save that to variable x, and then echo the record for the output file. If the record is a blank line it will just echo a blank line into the output. If the record does not begin with an H it will echo it with the variable x on the end.

0

With GNU awk, assuming not all the added numbers will be only 1 digit

gawk 'match($0, /^H0*([0-9]+)/, m) {n = m[1]} /^D/ {$0 = $0 n} 1' file

You must log in to answer this question.

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