LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   tab seperated textfile and write each field in a variable (https://www.linuxquestions.org/questions/programming-9/tab-seperated-textfile-and-write-each-field-in-a-variable-4175694145/)

Midyr 04-23-2021 04:28 AM

tab seperated textfile and write each field in a variable
 
Hello,

I have a textfile with tab separate content.

The goal is, to insert fiels3 in some lines.

The first line is without field3.

filed6 contains a space, which makes the trouble
Code:

F1      F2              F4      F5      F 6
F1      F2      F3      F4      F5      F 6

My idea was, to do this with awk, and write each field in a variable but it dosen't work as expected.
Code:

#!/bin/bash

while read
do

xy=($(awk -F '\t' '{print $1, $2, $3, $4, $5, $6}' ))
echo "Status; "${xy[0]}
echo "Start: "${xy[1]}
echo "End: "${xy[2]}
echo "Snr:: "${xy[3]}
echo "Ubknn: "${xy[4]}
echo "CN: "${xy[5]}
done < index.txt

Code:


Status; F1
Start: F2
End: F3
Snr:: F4
Ubknn: F5
CN: F

As you can see, F6 is cuted after the space.

Any idea to this?

Thanks

Midyr

pan64 04-23-2021 04:39 AM

you do not need to use awk at all:
https://github.com/koalaman/shellcheck/wiki/SC2206

Code:

xy=($(awk -F '\t' '{print $1, $2, $3, $4, $5, $6}' ))
awk will use tab, but shell will split the line second time using whitespace.
did you check xy[6] ?

Turbocapitalist 04-23-2021 04:50 AM

But if you do use AWK, keep in mind that the Field Separator (FS) and the Output Field Separator (OFS) are different variables.

Code:

xy=($(awk 'BEGIN {FS="\t"; OFS="\t"} {print $1, $2, $3, $4, $5, $6}' ))

Midyr 04-23-2021 04:54 AM

Quote:

Originally Posted by pan64 (Post 6244082)
you do not need to use awk at all:
https://github.com/koalaman/shellcheck/wiki/SC2206

Code:

xy=($(awk -F '\t' '{print $1, $2, $3, $4, $5, $6}' ))
awk will use tab, but shell will split the line second time using whitespace.
did you check xy[6] ?

Yes, xy[6] has the second part, I also tried some escapes, without success

grail 04-24-2021 03:56 AM

As the formatting wasn't saved for me on pasting, may I ask what is at field 3 in the line where it is missing?

I have assumed 2 spaces to make up for the missing field, so the below shows how bash can handle this:
Code:

!/usr/bin/env bash

while IFS=$'\t' read -ra fields
do
        printf "##%s##\n" "${fields[@]}"
done<your_file

And the output shows what it would pick up:
Code:

$ ./script.sh
##F1##
##F2##
##  ##
##F4##
##F5##
##F 6##
##F1##
##F2##
##F3##
##F4##
##F5##
##F 6##


pan64 04-24-2021 04:00 AM

Quote:

Originally Posted by Midyr (Post 6244087)
Yes, xy[6] has the second part, I also tried some escapes, without success

did you check the link I posted? You will see the solution (and explanation too).

shruggy 04-24-2021 04:13 AM

Quote:

Originally Posted by Midyr (Post 6244078)
The goal is, to insert field3 in some lines.

Then I don't understand what is the purpose of writing out each field to a variable.
Code:

awk -F\\t -vOFS=\\t '1,$3!=""&&$3="NEW"' index.txt

Midyr 05-03-2021 01:18 AM

Quote:

Originally Posted by shruggy (Post 6244399)
Then I don't understand what is the purpose of writing out each field to a variable.
Code:

awk -F\\t -vOFS=\\t '1,$3!=""&&$3="NEW"' index.txt


Thanks, that's, what i'm locking for!

MadeInGermany 05-04-2021 08:40 PM

Does it print all lines?
The following has an unconditional and explicit print
Code:

awk 'BEGIN { FS=OFS="\t" } $3=="" { $3="NEW" } { print }' < index.txt
The condition is $3==""

With bash builtins:
have a while read loop over the lines.
There is no good function to print with embedded delimiters,
so here is one.
Code:

#!/bin/bash
fs=$'\t'

prtjoin(){
  local fs=$1
  printf "%s" "$2"
  if [[ $# -gt 2 ]]
  then
    shift 2
    printf "$fs%s\n" "$@"
  fi
  printf "\n"
}

while IFS=$fs read -ra fields
do
  [[ -z ${fields[2]} ]] && fields[2]="NEW"
  prtjoin "$fs" "${fields[@]}"
done < index.txt

The condition is [[ -z ${fields[2]} ]]

And another variant:
Code:

#!/bin/bash
fs=$'\t'
while IFS=$fs read -ra fields
do
  [[ -z ${fields[2]} ]] && fields[2]="NEW"
  out=$(printf "$fs%s" "${fields[@]}"); printf "%s\n" "${out#$fs}"
done < index.txt


shruggy 05-05-2021 04:10 AM

@MadeInGermany. Two problems with your Bash code:

1) read counts consecutive runs of an IFS character as one delimiter. Probably not was the OP wanted.
2) \n in printf "$fs%s\n" "$@" is unnecessary.

And a small enhancement:
Code:

out=$(printf "$fs%s" "${fields[@]}")
is the same as
Code:

printf -v out "$fs%s" "${fields[@]}"

pan64 05-05-2021 04:30 AM

or probably
Code:

printf -v out "$fs%s" "${fields[*]}"


All times are GMT -5. The time now is 06:18 PM.