Max Sergeev
Max Sergeev

Reputation: 55

Change column values by program in Unix

I have an input like this:

12 abc 13 14
13 def 14 15
1  lce 22 14

And I want to change it by applying the program ./program to the second column:

12 P1 13 14
13 P2 14 15
1  P3 22 13

(if echo "abc" | ./program returns "P1",echo "def" | ./program returns "P2", etc.). How I can do that?

Upvotes: 1

Views: 106

Answers (6)

Jotne
Jotne

Reputation: 41460

Why not take all in awk, do you need the "program"?

awk 'BEGIN {n=split("abc def lce",q," ");for (i=1;i<=n;i++) d[q[i]]="P"i} {sub($2,d[$2])}8' file
12 P1 13 14
13 P2 14 15
1  P3 22 14

How it works

awk '
BEGIN {                             # Begin block
    n=split("abc def lce",q," ")    # split the list of data in to array "q" and set "n" to number of elements
    for (i=1;i<=n;i++)              # loop trough  all elements
        d[q[i]]="P"i                # assing P1, P2 etc to first, second element "d[abc]=P1" etc
    } 
    {sub($2,d[$2])}                 # change filed 2 to new element
    8                               # print the new line
    ' file                          # input file

If table with "P" data is not sequel, you can add it just like other table:

awk 'BEGIN {n=split("abc def lce",q," ");split("P2 Q4 A3",r," ");for (i=1;i<=n;i++) d[q[i]]=r[i];print d["def"]}'

Upvotes: 1

csiu
csiu

Reputation: 3279

WITH REGARDS TO: if echo "abc" | ./program returns "P1", echo "def" | ./program returns "P2", etc.). How I can do that?

The program script might look something like:

INFILE=input.txt ## your input file

## exits if no standard input
if [ -t 0 ] ; then echo "Error: No STDIN" && exit ; fi

## do something
while read line; do
    awk -v input=$line '$2 == input {print "P"NR}' $INFILE
done
  • after you specify the INFILE in the program script...
  • echo "abc" | sh program returns "P1"
  • echo "def" | sh program returns "P2"

WHEREAS: if you just want the output to be

12 P1 13 14  
13 P2 14 15  
1  P3 22 13

You can use the following one-liner:

awk 'BEGIN {OFS="\t"} {$2="P"NR}1' input.txt > outfile.txt

Upvotes: 0

cimarron
cimarron

Reputation: 431

This should do what you want as an awk script

{
   "echo "$2" | ./program" | getline result;
   $2 = result;
   print;
}

Upvotes: 1

Noctua
Noctua

Reputation: 5218

I think the easiest way would be with a while loop.

while read -r line; do
    old="$(echo "$line" | tr -s ' ' | cut -d ' ' -f 2)"
    new="$(echo "$old" | ./program)"
    echo "$line" | sed "s/$old/$new/"
done

Remarks:

  • I use tr because your columns might be aligned. tr -s ' ' replaces multiple spaces by one.
  • I'm using sed to change your line, in order not to mess with the alignment.

Upvotes: 0

damienfrancois
damienfrancois

Reputation: 59395

while read a b c d ; do echo $a $(./program <<< $b) $c $d ; done < t

where t is the name of the file.

Upvotes: 2

that other guy
that other guy

Reputation: 123750

Use a while read loop:

while read -r one two rest
do
  echo "$one $(./program <<< "$two") $rest"
done < inputfile

Upvotes: 4

Related Questions