0

I've a tab/space delimited file as:

31000BL        50014_10011 
25467BL        50050_10003 
47406BL        50001_10015 
40831BL        50114_10006 
40830BL        50114_10009

Two columns. I use a while loop to read this:

while read LINE; do 
    printf "$LINE\n" 
    old=($(echo $LINE | awk '{print $1}')) 
    new=($(echo $LINE | awk '{print $2}'))  
    ll=$old'^V<tab>'$new                  #I need to work here.   
    printf "$ll\n" 
done < update_ids.txt

The output I'd like is

31000BL\t50014_10011\n25467BL\t50050_10003\n

There is a literal tab and new line character. I cannot concatenate or print with tab and/or new line character.

ilkkachu
  • 138,973

2 Answers2

4

I'm not quite sure that I understand correctly, but if you'd just want to make sure that there's a literal tab character between your two columns, you can do that in a single awk invocation:

awk -v OFS='\t' '{ $1=$1; print }' file >newfile

Setting OFS on the command line to \t sets the output field separator to a tab character. Using $1=$1 will force awk to re-form the current record, and the subsequent print would print it out with whatever whitespace it originally used as delimiter replaced with tabs.

The result is written to newfile through the use of a redirection.

Alternatively, use a more explicit printf() call:

awk '{ printf("%s\t%s\n", $1, $2) }' file >newfile

Note that this only handles exactly two columns, whereas the first awk program would work with data containing multiple columns, without modification.

Related to the question:

Kusalananda
  • 333,661
  • i think you mean $0=$0 in the first example. – Lesmana Jan 28 '19 at 16:27
  • @lesmana Do I? That would not cause awk to re-form the current record, which means that the value of OFS would not be inserted between the fields. – Kusalananda Jan 28 '19 at 16:49
  • i learned something new. $1=$1 causes rewriting of $0 with OFS. here is an explanation: https://stackoverflow.com/a/41941143 thank you. – Lesmana Jan 28 '19 at 21:28
0

The shell read command can read into multiple variables. You need to set the IFS variable to be a tab, which in bash you do with ANSI-C Quoting: IFS=$'\t'

For output, the printf builtin command is what you want.

while IFS=$'\t' read -r old new; do 
    printf '%s\t%s\n' "$old" "$new"
done < update_ids.txt

To save tab-separated data into a variable you can do:

var=$(printf '%s\t%s\n' "$old" "$new")
# or
printf -v var '%s\t%s\n' "$old" "$new"
# or this quoting disaster
var="$old"$'\t'"$new"

ref: https://www.gnu.org/software/bash/manual/bashref.html#index-printf

glenn jackman
  • 85,964