print columns from bash variable

  • Follow


Hi,

I have this bash variable:
MARCA_TABELA="mencionadoo  $7 $3 $1"

and I want to add an extra column to a data file like this:
cat $FICHEIRO_TEMP | awk --field-separator=";" --assign 
mt="${MARCA_TABELA}" '{OFS=";"; print $0 , mt }' > $FICHEIRO

The problem is that awk does not add "mencionadoo   content of column 7   
"content of column 3   content of column 1"
as the last column.  

Instead, for each line, awk adds: "mencionadoo $7 $3 $1".
The expansion (or conversion) of $7 $3 $1 is not performed.

How can I make it work?


Luis
0
Reply luislupeXXX (17) 3/9/2009 12:50:33 PM

Luis P. Mendes wrote:
> Hi,
> 
> I have this bash variable:
> MARCA_TABELA="mencionadoo  $7 $3 $1"
> 
> and I want to add an extra column to a data file like this:
> cat $FICHEIRO_TEMP | awk --field-separator=";" --assign 
> mt="${MARCA_TABELA}" '{OFS=";"; print $0 , mt }' > $FICHEIRO

Since it does not change, you should assign OFS in the BEGIN block, or 
using --assign (or its standard equivalent -v).

> The problem is that awk does not add "mencionadoo   content of column 7   
> "content of column 3   content of column 1"
> as the last column.  
> 
> Instead, for each line, awk adds: "mencionadoo $7 $3 $1".
> The expansion (or conversion) of $7 $3 $1 is not performed.

Awk does not do that kind of reevaluation. One solution here could be to 
create two shell variables in the first place, one with "mencionadoo" 
(and all other needed fixed strings), and another one with the list of 
fields to print, without the $, like eg "7 3 1". Then you could split 
the second variable and put the field numbers in an array. Example:

$ echo "$FIXED"
mencionadoo
$ echo "$MARCA_TABELA"
7 3 1
$ awk -F ';' -v fixed="$FIXED" -v mt="$MARCA_TABELA" -v OFS=';' '
BEGIN{n=split(mt,ls,/ /)}
{str=ofs="";for(i=1;i<=n;i++){str=str ofs $(ls[i]);ofs=OFS}
  print $0, fixed, str}'


Or if you only have a single fixed part, you can do all the parsing in 
awk (assumes the first word is the fixed string):

$ echo "$MARCA_TABELA"
mencionadoo 7 3 1
$ awk -F ';' -v mt="$MARCA_TABELA" -v OFS=';' '
BEGIN{
   match(mt,/ /);               # look where first word ends
   fixed=substr(mt,1,RSTART-1)  # extract fixed part
   mt=substr(mt,RSTART+1)       # remove fixed part
   n=split(mt,ls,/ /)           # get fields
}
{# main body same as before}'

Hope that helps.

-- 
awk 'BEGIN{O="~"~"~";o="=="=="==";o+=+o;x=O""O;while(X++<=x+o+o)c=c"%c";
printf c,(x-O)*(x-O),x*(x-o)-o,x*(x-O)+x-O-o,+x*(x-O)-x+o,X*(o*o+O)+x-O,
X*(X-x)-o*o,(x+X)*o*o+o,x*(X-x)-O-O,x-O+(O+o+X+x)*(o+O),X*X-X*(x-O)-x+O,
O+X*(o*(o+O)+O),+x+O+X*o,x*(x-o),(o+X+x)*o*o-(x-O-O),O+(X-x)*(X+O),x-O}'
0
Reply Dave 3/9/2009 1:50:36 PM


Mon, 09 Mar 2009 13:50:36 +0000, Dave B escreveu:

> Luis P. Mendes wrote:
>> Hi,
>> 
>> I have this bash variable:
>> MARCA_TABELA="mencionadoo  $7 $3 $1"
>> 
>> and I want to add an extra column to a data file like this: cat
>> $FICHEIRO_TEMP | awk --field-separator=";" --assign
>> mt="${MARCA_TABELA}" '{OFS=";"; print $0 , mt }' > $FICHEIRO
> 
> Since it does not change, you should assign OFS in the BEGIN block, or
> using --assign (or its standard equivalent -v).
> 
>> The problem is that awk does not add "mencionadoo   content of column 7
>> "content of column 3   content of column 1" as the last column.
>> 
>> Instead, for each line, awk adds: "mencionadoo $7 $3 $1". The expansion
>> (or conversion) of $7 $3 $1 is not performed.
> 
> Awk does not do that kind of reevaluation. One solution here could be to
> create two shell variables in the first place, one with "mencionadoo"
> (and all other needed fixed strings), and another one with the list of
> fields to print, without the $, like eg "7 3 1". Then you could split
> the second variable and put the field numbers in an array. Example:
> 
> $ echo "$FIXED"
> mencionadoo
> $ echo "$MARCA_TABELA"
> 7 3 1
> $ awk -F ';' -v fixed="$FIXED" -v mt="$MARCA_TABELA" -v OFS=';' '
> BEGIN{n=split(mt,ls,/ /)}
> {str=ofs="";for(i=1;i<=n;i++){str=str ofs $(ls[i]);ofs=OFS}
>   print $0, fixed, str}'
> 
> 
> Or if you only have a single fixed part, you can do all the parsing in
> awk (assumes the first word is the fixed string):
> 
> $ echo "$MARCA_TABELA"
> mencionadoo 7 3 1
> $ awk -F ';' -v mt="$MARCA_TABELA" -v OFS=';' ' BEGIN{
>    match(mt,/ /);               # look where first word ends
>    fixed=substr(mt,1,RSTART-1)  # extract fixed part
>    mt=substr(mt,RSTART+1)       # remove fixed part n=split(mt,ls,/ /)  
>            # get fields
> }
> {# main body same as before}'
> 
> Hope that helps.

Hello Dave,

thank you for your support, but I still can't have it working.

Please consider:
$ cat xx.csv
"a_col1";"a_col2";"a_col3";"a_col4";"a_col5";"a_col6";"a_col7";"a_col8";"a_col9";"a_col10";"a_col11"
"b_col1";"b_col2";"b_col3";"b_col4";"b_col5";"b_col6";"b_col7";"b_col8";"b_col9";"b_col10";"b_col11"

and the following script:
  1 MARCA_TABELA="mencionadoo 7 3 1 "
  2 echo "$MARCA_TABELA"
  3 cp 1.csv xx.csv
  4 cat xx.csv | awk -F ';' -v mt="$MARCA_TABELA" -v OFS=';' ' BEGIN{
  5    match(mt,/ /);               # look where first word ends
  6       fixed=substr(mt,1,RSTART-1)  # extract fixed part
  7          mt=substr(mt,RSTART+1)       # remove fixed part n=split
(mt,ls,/ /)
  8          n=split(mt,ls,/ /)
  9           }
 10 {str=ofs="";for(i=1;i<=n;i++){str=str ofs $(ls[i]);ofs=OFS}
 11   print str }' > yy.csv

$ cat yy.csv
"a_col7";"a_col3";"a_col1";"a_col1";"a_col2";"a_col3";"a_col4";"a_col5";"a_col6";"a_col7";"a_col8";"a_col9";"a_col10";"a_col11"
"b_col7";"b_col3";"b_col1";"b_col1";"b_col2";"b_col3";"b_col4";"b_col5";"b_col6";"b_col7";"b_col8";"b_col9";"b_col10";"b_col11"

It shows the 7th, 3rd and 1st columns as I'd expect, but repeats all the 
columns afterwards, and I don't understand why.

Luis
0
Reply Luis 3/9/2009 5:10:09 PM

Luis P. Mendes wrote:

> Please consider:
> $ cat xx.csv
> "a_col1";"a_col2";"a_col3";"a_col4";"a_col5";"a_col6";"a_col7";"a_col8";"a_col9";"a_col10";"a_col11"
> "b_col1";"b_col2";"b_col3";"b_col4";"b_col5";"b_col6";"b_col7";"b_col8";"b_col9";"b_col10";"b_col11"
> 
> and the following script:
>   1 MARCA_TABELA="mencionadoo 7 3 1 "
>   2 echo "$MARCA_TABELA"
>   3 cp 1.csv xx.csv
>   4 cat xx.csv | awk -F ';' -v mt="$MARCA_TABELA" -v OFS=';' 'BEGIN{
>   5    match(mt,/ /);                 # look where first word ends
>   6    fixed=substr(mt,1,RSTART-1)    # extract fixed part
>   7    mt=substr(mt,RSTART+1)         # remove fixed part
>   8    n=split(mt,ls,/ /)
>   9 }
>  10 {str=ofs="";for(i=1;i<=n;i++){str=str ofs $(ls[i]);ofs=OFS}
>  11   print str }' > yy.csv
> 
> $ cat yy.csv
> "a_col7";"a_col3";"a_col1";"a_col1";"a_col2";"a_col3";"a_col4";"a_col5";"a_col6";"a_col7";"a_col8";"a_col9";"a_col10";"a_col11"
> "b_col7";"b_col3";"b_col1";"b_col1";"b_col2";"b_col3";"b_col4";"b_col5";"b_col6";"b_col7";"b_col8";"b_col9";"b_col10";"b_col11"
> 
> It shows the 7th, 3rd and 1st columns as I'd expect, but repeats all the 
> columns afterwards, and I don't understand why.

Works fine for me. Are you sure you pasted the exact code you are using? 
Just copy/paste it, without adding line numbers or anything.

-- 
awk 'BEGIN{O="~"~"~";o="=="=="==";o+=+o;x=O""O;while(X++<=x+o+o)c=c"%c";
printf c,(x-O)*(x-O),x*(x-o)-o,x*(x-O)+x-O-o,+x*(x-O)-x+o,X*(o*o+O)+x-O,
X*(X-x)-o*o,(x+X)*o*o+o,x*(X-x)-O-O,x-O+(O+o+X+x)*(o+O),X*X-X*(x-O)-x+O,
O+X*(o*(o+O)+O),+x+O+X*o,x*(x-o),(o+X+x)*o*o-(x-O-O),O+(X-x)*(X+O),x-O}'
0
Reply Dave 3/9/2009 5:17:59 PM

Mon, 09 Mar 2009 17:17:59 +0000, Dave B escreveu:

> Luis P. Mendes wrote:
> 
>> Please consider:
>> $ cat xx.csv
>> 
"a_col1";"a_col2";"a_col3";"a_col4";"a_col5";"a_col6";"a_col7";"a_col8";"a_col9";"a_col10";"a_col11"
>> 
"b_col1";"b_col2";"b_col3";"b_col4";"b_col5";"b_col6";"b_col7";"b_col8";"b_col9";"b_col10";"b_col11"
>> 
>> and the following script:
>>   1 MARCA_TABELA="mencionadoo 7 3 1 "
>>   2 echo "$MARCA_TABELA"
>>   3 cp 1.csv xx.csv
>>   4 cat xx.csv | awk -F ';' -v mt="$MARCA_TABELA" -v OFS=';' 'BEGIN{ 5 
>>     match(mt,/ /);                 # look where first word ends 6   
>>   fixed=substr(mt,1,RSTART-1)    # extract fixed part 7   
>>   mt=substr(mt,RSTART+1)         # remove fixed part 8   
>>   n=split(mt,ls,/ /)
>>   9 }
>>  10 {str=ofs="";for(i=1;i<=n;i++){str=str ofs $(ls[i]);ofs=OFS} 11  
>>  print str }' > yy.csv
>> 
>> $ cat yy.csv
>> 
"a_col7";"a_col3";"a_col1";"a_col1";"a_col2";"a_col3";"a_col4";"a_col5";"a_col6";"a_col7";"a_col8";"a_col9";"a_col10";"a_col11"
>> 
"b_col7";"b_col3";"b_col1";"b_col1";"b_col2";"b_col3";"b_col4";"b_col5";"b_col6";"b_col7";"b_col8";"b_col9";"b_col10";"b_col11"
>> 
>> It shows the 7th, 3rd and 1st columns as I'd expect, but repeats all
>> the columns afterwards, and I don't understand why.
> 
> Works fine for me. Are you sure you pasted the exact code you are using?
> Just copy/paste it, without adding line numbers or anything.

Ok, there's the copy of it.

MARCA_TABELA="mencionadoo 7 3 1 "
echo "$MARCA_TABELA"
cp 1.csv xx.csv
cat xx.csv | awk -F ';' -v mt="$MARCA_TABELA" -v OFS=';' ' BEGIN{
   match(mt,/ /);               # look where first word ends
      fixed=substr(mt,1,RSTART-1)  # extract fixed part
         mt=substr(mt,RSTART+1)       # remove fixed part n=split
(mt,ls,/ /)
         n=split(mt,ls,/ /)
          }
{str=ofs="";for(i=1;i<=n;i++){str=str ofs $(ls[i]);ofs=OFS}
  print str }' > yy.csv

I tried on the command line and the result is the same:
$ cat yy.csv
"a_col7";"a_col3";"a_col1";"a_col1";"a_col2";"a_col3";"a_col4";"a_col5";"a_col6";"a_col7";"a_col8";"a_col9";"a_col10";"a_col11"
"b_col7";"b_col3";"b_col1";"b_col1";"b_col2";"b_col3";"b_col4";"b_col5";"b_col6";"b_col7";"b_col8";"b_col9";"b_col10";"b_col11"

$ awk --version
GNU Awk 3.1.5

Luis
0
Reply Luis 3/9/2009 5:23:59 PM

Luis P. Mendes wrote:

> Ok, there's the copy of it.
> 
> MARCA_TABELA="mencionadoo 7 3 1 "

Ah, here is the problem (it was there before too, sorry for missing it). 
Remove the trailing space:

MARCA_TABELA="mencionadoo 7 3 1"

The trailing space causes an empty element to be created in the array 
ls, which evaluates to $0 (ie, the whole line) when referenced with 
$(ls[i]).

-- 
awk 'BEGIN{O="~"~"~";o="=="=="==";o+=+o;x=O""O;while(X++<=x+o+o)c=c"%c";
printf c,(x-O)*(x-O),x*(x-o)-o,x*(x-O)+x-O-o,+x*(x-O)-x+o,X*(o*o+O)+x-O,
X*(X-x)-o*o,(x+X)*o*o+o,x*(X-x)-O-O,x-O+(O+o+X+x)*(o+O),X*X-X*(x-O)-x+O,
O+X*(o*(o+O)+O),+x+O+X*o,x*(x-o),(o+X+x)*o*o-(x-O-O),O+(X-x)*(X+O),x-O}'
0
Reply Dave 3/9/2009 5:31:24 PM

Mon, 09 Mar 2009 17:31:24 +0000, Dave B escreveu:

> Luis P. Mendes wrote:
> 
>> Ok, there's the copy of it.
>> 
>> MARCA_TABELA="mencionadoo 7 3 1 "
> 
> Ah, here is the problem (it was there before too, sorry for missing it).
> Remove the trailing space:
> 
> MARCA_TABELA="mencionadoo 7 3 1"
> 
> The trailing space causes an empty element to be created in the array
> ls, which evaluates to $0 (ie, the whole line) when referenced with
> $(ls[i]).

I printed n before and saw that its value was 4 instead of 3, but didn't 
guess the empty element would evaluate to $0.

Thank you Dave, it works perfectly, now!

Luis
0
Reply Luis 3/9/2009 6:39:05 PM

6 Replies
363 Views

(page loaded in 0.086 seconds)

Similiar Articles:













7/22/2012 5:01:22 AM


Reply: