Arash Shams
Arash Shams

Reputation: 186

parse a text file in shell scripting

I want to read a file and print it to stdout using shellscript . in python rsplit can do the job but i search and find awk but i cant understand .

file1:

#begin cow
Host cow
    HostName 172.18.0.10
    User root
    Port 22
#end cow
#begin dns2
Host dns2
    HostName 172.20.4.80
    User root
    Port 22
#end dns2
#begin dns1
Host dns1
    HostName 172.20.4.75
    User root
    Port 22
#end dns1
#begin dns3
Host dns3
        HostName 172.20.4.76
        User root
        Port 22
#end dns3
#begin dns4
Host dns4
        HostName 172.20.4.77
        User root
        Port 22
#end dns4
#begin dns5
Host dns5
        HostName 172.20.4.78
        User root
        Port 22
#end dns5
#begin dns6
Host dns6
        HostName 172.20.4.79
        User root
        Port 22
#end dns6

after parsing its turns to

Host: cow  Hostname: 172.18.0.10 User: root Port: 22
Host: dns2 Hostname: 172.20.4.80 User: root Port: 22
Host: dns1 Hostname: 172.20.4.75 User: root Port: 22
Host: dns3 Hostname: 172.20.4.76 User: root Port: 22
Host: dns4 Hostname: 172.20.4.77 User: root Port: 22
Host: dns5 Hostname: 172.20.4.78 User: root Port: 22
Host: dns6 Hostname: 172.20.4.79 User: root Port: 22

any one can help me about this thank you

Upvotes: 0

Views: 128

Answers (2)

NeronLeVelu
NeronLeVelu

Reputation: 10039

Based on your text (assume structure are complete (begin -> end), there is no empty line, ...)

awk -v "Sep=\t" '/^#begin/{Infos="";next}/^#end/{print Infos;next}{Infos = Infos ($1~/^Host$/ ? "" : Sep) $1 ": " $2}' YourFile

Sep is your separator between info sub sequence.

Same with a filter (only print if filter is the same; here if host is cow or boy)

awk -v "Sep=\t" -v"Filter=^cow$|^boy$" '
   /^#begin/{Infos="";PassFilter=0;next}
   /^#end/&&PassFilter{print Infos;next}
   $1~/^Host$/{PassFilter=$2~Filter}
   {Infos = Infos ($1~/^Host$/ ? "" : Sep) $1 ": " $2}
   ' YourFile

Explanation:

  • /^#begin/{Infos="";next} reset string to print every line starting by `#begin, go to next line of source file (don't treat following instruction).
  • /^#end/&&PassFilter{print Infos;next} when line start with #end and the variable PassFilter is true (=1), print the string content of Infos, go to next line of source file.
  • $1~/^Host$/{PassFilter=$2~Filter} when line first word is Host, the variable PassFilter is set to true if second word contains/corresponds to the regex into Filter variable (^cow$|^boy$ in this case).
  • {Infos = Infos ($1~/^Host$/ ? "" : Sep) $1 ": " $2} Add content of the current line (first ($1) then : and finally second word in fact) to variable Infos with a separator if not line withHost` as first word.

Upvotes: 2

Arjun Mathew Dan
Arjun Mathew Dan

Reputation: 5318

Since you haven't mentioned your awk command in the question, i assume u are looking for a solution with awk and an explanation.

AMD$ awk '!/^#/{printf $1": "$2" "}/end/{print '\n'}' File

Host: cow HostName: 172.18.0.10 User: root Port: 22
Host: dns2 HostName: 172.20.4.80 User: root Port: 22
Host: dns1 HostName: 172.20.4.75 User: root Port: 22
Host: dns3 HostName: 172.20.4.76 User: root Port: 22
Host: dns4 HostName: 172.20.4.77 User: root Port: 22
Host: dns5 HostName: 172.20.4.78 User: root Port: 22
Host: dns6 HostName: 172.20.4.79 User: root Port: 22

For all lines NOT beginning with # (!/^#/), printf the 1st and 2nd fields seperated by : and space. Continue this until we hit the end pattern (/end/), where we would print the new line.

In case you are looking for an explanation for the awk command you already have, mention it in the question.

Upvotes: 5

Related Questions