Santhosh Ram
Santhosh Ram

Reputation: 93

Insert a string at a specific position (fixed length file)

I'm trying to insert a string "abcd" at the position of 80 in each rows of a fixed length file.

Input file

1212121212121212121213231232345    00000003088 234235235321      MISS WAN
1212121212121212121213231232345    00000003088 324556346366      MISS NISCH
1212121212121212121213231232345    00000003088 547478657588      MISS RACHEL
1212121212121212121213231232345    00000009781 313156475788      MR & MRS ROCK

The length of each records are

awk '{print length}' temp.txt
74
76
77
79

I wasn't able to insert data at 80 and I've tried the below commands

sed "s/.\{80\}/&abcd/" test.txt
awk -vFS="" -vOFS="" '{$80=$80"abcd"}1' test.txt

I thought that I should first increase the length of the records so then I can use the above commands..
To insert spaces

sed -e "s/.\{75\}/&              /g" test.txt
sed 's/$/        /" test.txt

Inside a loop

while read line
do
printf "$line        " >>temp.txt
done <test.txt

Most of the time the above spaces get amended with the next lines and lost some of the contents as shown below..

4044046160710301740053062257440    00000003088 850052246976      MISS WAN
    046160710301740053062257440    00000003088 850052246976      MISS NISCH
    046160710301740053062257440    00000003088 850052246976      MISS RACHEL
2011888360797600140053062257440    00000009781 851011576287      MR & MRS ROCK

Expected answer:

4044046160710301740053062257440    00000003088 850052246976      MISS WAN       abcd
4044046160710301740053062257440    00000003088 850052246976      MISS NISCH     abcd
4044046160710301740053062257440    00000003088 850052246976      MISS RACHEL    abcd
2011888360797600140053062257440    00000009781 851011576287      MR & MRS ROCK  abcd

Any guidelines towards the right answer would be much appreciated.

Upvotes: 2

Views: 1384

Answers (5)

Walter A
Walter A

Reputation: 20032

I can't see where you get stuck using sed "s/$/ /" test.txt and sed "s/.\{80\}/&abcd/" test.txt. How did you combine them? You don't want -i for the first command, that would modify the inputfile. Incorrect is

# error, did you try this:
sed "s/$/        /" test.txt | sed "s/.\{80\}/&abcd/" test.txt

The second sed will not look at the output of the first command, but will start with the original test.txt.
You can combine them (I also used single quotes) with

sed 's/$/        /' test.txt | sed 's/.\{80\}/&abcd/'
or shorter
sed 's/$/        /;s/.\{80\}/&abcd/' test.txt

The result might look good, but you can have additional spaces after abcd. Better is

sed -r 's/$/        /;s/(.{80}).*/\1abcd/' test.txt

The first part of the comand is ugly. You can write your own loop like

while IFS= read -r line; do
   printf "%-80sabcd\n" "${line}"
done < test.txt

This is a difficult method where you can use the simple awk given by @karakfa.

Upvotes: 0

anubhava
anubhava

Reputation: 786111

You may use gnu awk command:

awk -v RS='\r?\n' -v p='80' -v s='abcd' '{
    pad=""; for (i=length(); i<=p; i++) pad=pad " "; print $0 pad s}' file

1212121212121212121213231232345    00000003088 234235235321      MISS WAN        abcd
1212121212121212121213231232345    00000003088 324556346366      MISS NISCH      abcd
1212121212121212121213231232345    00000003088 547478657588      MISS RACHEL     abcd
1212121212121212121213231232345    00000009781 313156475788      MR & MRS ROCK   abcd

Note use -v RS='\r?\n' which sets record separator as optional \r followed by \n. This to address case when input file has DOS line breaks.

For loop starts from length of each line to desired position (being passed from command line in variable p) and appends a space in pad variable. Finally we print each row followed by padded space and new string.

Upvotes: 2

mivk
mivk

Reputation: 15039

Yet another way, combining karakfa's awk line, and the use of GNU wc to get the maximum line length.

file="./your_file"

awk -v sp=4 -v max="$(wc -L "$file")" '{printf "%-"max+sp"s%s\n",$0,"abcd"}' "$file"

The -v options initialize variables max with the maximum line length in the file, and sp for the number of spaces to use after the max line length.

Output:

4044046160710301740053062257440    00000003088 850052246976      MISS WAN         abcd
    046160710301740053062257440    00000003088 850052246976      MISS NISCH       abcd
    046160710301740053062257440    00000003088 850052246976      MISS RACHEL      abcd
2011888360797600140053062257440    00000009781 851011576287      MR & MRS ROCK    abcd

Upvotes: 0

karakfa
karakfa

Reputation: 67567

a simpler awk

$ awk '{printf "%-80s%s\n",$0,"abcd"}' file

1212121212121212121213231232345    00000003088 234235235321      MISS WAN       abcd
1212121212121212121213231232345    00000003088 324556346366      MISS NISCH     abcd
1212121212121212121213231232345    00000003088 547478657588      MISS RACHEL    abcd
1212121212121212121213231232345    00000009781 313156475788      MR & MRS ROCK  abcd

Upvotes: 3

RavinderSingh13
RavinderSingh13

Reputation: 133770

Solution as per OP's requirement for adding spaces as per length of 80: In case you have control M characters in your Input_files and you want to remove them then use:

tr -d '\r' < Input_file > temp_file && mv temp_file Input_file

then run following code:

awk -v var="80" '{printf("%s%"var-length($0)+1"s%s\n",$0,OFS,"abcd")}' Input_file


2nd solution(more generic one): Could you please try following, this solution will look for maximum length of the line in whole Input_file and will add spaces according to it and newly entered last field will be in same alignment with all other lines.

awk '
FNR==NR{
  len=length($0)>len?length($0):len
  next
}
{
  printf("%s%"len-length($0)+1"s%s\n",$0,OFS,"abcd")
}
'  Input_file  Input_file

Upvotes: 2

Related Questions