Alex
Alex

Reputation: 297

Bash read file line by line and use awk

I have a sample.txt file in Username:Firstname:Lastname:Telephone number format (with several lines, and I want to create a script that converts every line into this format:

uid: Username
cn: LastnameFirstname
sn: Firstname
tel:Telephone number

So far I've managed to create the citire function that reads and prints OK only if the sample.txt has one line.

citire () {
uid=$1
l=$2
while read -r line
do
 name=$line
  if [ -z "$3" ]
  then
  echo -e "$uid:`echo $name|awk -F  ":" '{print $"'$l'"}'`"
  else
  l2=$3
  echo -e "$uid: `echo $name|awk -F  ":" '{print $"'$l'" $"'$l2'"}'`"
 fi
 done < /home/alexandrumohora/teste/sample.txt  
}

citire uid 1
citire cn 3 2
citire sn 2
citire tel 4

Can you please tell me what should I modify to make it print each record (line of the file) at a time?

Thank you!

Upvotes: 1

Views: 13745

Answers (2)

janos
janos

Reputation: 124834

I don't know if you just want to output all records in a fixed format, or if you want the format to be configurable with the citire function.

Here's a simple version that outputs in a fixed format, the used in your example:

#!/bin/bash
data=/home/alexandrumohora/teste/sample.txt
citire() {
    while IFS=: read uid sn ln tel; do
        echo uid: $uid
        echo cn: $ln$sn
        echo sn: $sn
        echo tel:$tel
    done < "$data"
}
citire

And here's a more sophisticated version where citire takes a "recipe", making the function reusable with different formats:

#!/bin/bash
data=/home/alexandrumohora/teste/sample.txt
citire() {
    while IFS=: read -a fields; do
        for i; do
            case $i in
                [0-9]) printf %s "${fields[$i]}" ;;
                BR) echo ;;
                *) printf '%s: ' "$i" ;;
            esac
        done
    done < "$data"
}
citire uid 0 BR cn 2 1 BR sn 1 BR tel 3 BR

Explanation:

  • citire interprets the "recipe" by looping over each item:
    • digit i -- print the field i, 0-based
    • "BR" -- print a line break
    • anything else -- use as a label: print it and a ": " after it
  • Put each line in the array fields, using : as the field separator

If you don't like the recipe format, you could probably change the script to make it work like this instead:

citire uid 1 cn 3 2 sn 2 tel 4

Upvotes: 1

Zsolt Botykai
Zsolt Botykai

Reputation: 51693

So you basically want something like this which works without bash:

 gawk 'BEGIN {FS=":"}
       { print "uid:" $1
         print " cn:" $3, $2
         print " sn:" $2
         print "tel:" $4
       }' INPUTFILE

Edit: also see the comments below my answer for proper solutions, credit goes to them!

The shortest solution might be:

awk -F: { printf "uid: %s\n cn: %s %s\n sn: %s\ntel: %s\n", $1, $3, $2, $3, $4 } INPUTFILE

Upvotes: 5

Related Questions