|
Author |
Message |
|
|
Posted : Mon, 12 May 2008 14:45:40
Subject :
parsing config file via bash script
Hello to all Linux users! I am new to bash scripting, but an old Linux user. I have to make bash script which will return only the last row from this txt file:
one|two|three
four|five|six
seven|eight|nine
so that result will be:
three
six
nine
"|" are delimiters. Of course it is not necessary, it can be any other character than "|".
If anyone knows please respond. Thank you!
|
|
|
|
Khabi
|
Posted : Mon, 12 May 2008 19:13:08
Subject :
Re: parsing config file via bash script
Simple way is to use awk.
if all of those lines were in a file called test.txt this one line would print out the last column:
awk -F'|' '{print $NF}' test.txt
-F being the filed delimiter (in this case |)
$NF telling it to be the last column (you can make that $2 or any other number to tell it specifically what column you want)
:)
[Modified by: Khabi on May 12, 2008 07:13 PM]
|
|
asmerm
|
Posted : Tue, 13 May 2008 08:22:23
Subject :
Re: parsing config file via bash script
Thanks a lot! It works like a charm.
Also thanks for explanations!
|
|
Khabi
|
Posted : Tue, 13 May 2008 22:52:04
Subject :
parsing config file via bash script
No problem! Glad I could help out :)
|
|
AR
|
Posted : Thu, 15 May 2008 18:25:00
Subject :
parsing config file via bash script
I think cut is easier on your resources like "cut -f3 -d\| filename"
-f3 being the third field and -d\| being the separator (pipe has to be escaped hence the \)
example:
$ echo '1232|4565|23432' | cut -f3 -d\|
23432
|
|
xi
|
Posted : Sat, 17 May 2008 14:06:27
Subject :
Re: parsing config file via bash script
Assuming the separator symbol is not part of any of the words, this also works:
[code=xml]cat file.lst | while read line ; do
echo "${line##*|}"
done[/code]
|
|
Slarti
|
Posted : Mon, 19 May 2008 10:22:10
Subject :
Re: parsing config file via bash script
The cut statement above only works if there are exactly three fields per line. I don't know awk to comment on that.
Just to complete the trio, thought I'd give the sed version which prints the last field on each line, rather than the third field:
[code=xml]sed -e "s/.*|\([^|]*\)$/\1/" test.txt[/code]
To avoid lines which don't have any fields on them, such as comments, use:
[code=xml]sed -n -e "s/.*|\([^|]*\)$/\1/p" test.txt[/code]
To print the third field, even if there are more than three fields use:
[code=xml]sed -n -e "s/[^|]*|[^|]*|\([^|]*\)|*.*$/\1/p" test.txt[/code]
|
|
AR
|
Posted : Mon, 19 May 2008 13:37:16
Subject :
Re: Re: parsing config file via bash script
[quote=Slarti]The cut statement above only works if there are exactly three fields per line. I don't know awk to comment on that.[/quote]
I think you're wrong. It will work fine as long as it's at least three fields. Otherwise it returns an empty string/line (which is still fine).
example:
$ echo '1232|23423|23432|2398746832|3242342|234324' | cut -f3 -d\|
23432
$ echo -e '1232|234324' | cut -f3 -d\|
$
I like the bash pattern substitution one :)
|
|
Khabi
|
Posted : Mon, 19 May 2008 19:20:41
Subject :
parsing config file via bash script
I still stand by my awk example. But thats probably because I try to use as few pipes as possible when i write anything in bash. It just makes it hard to maintain after time, especially because when you get into the habit of using pipes sooner or later your going to have a command with 5-10 pipes in it (I've seen it in old scripts in the place I work, makes me cringe :P ).
If you just want the 3rd field in the awk example just change $NR to $3 and thats all you'll get. If the the line doesn't have a third field it just outputs a newline. :)
|
|
AR
|
Posted : Sat, 24 May 2008 12:47:52
Subject :
parsing config file via bash script
I must confess I love pipes but it's probably just me :)
For some reason I have a feeling that using dedicated binaries (eg. cut) is faster than awk especially if two sides of the pipe can run on a different CPUs. I often have to parse these neverending log files and it matters there. I might be completely wrong though, I mean, they can't run in parallel since one is connected to the other.
You definitely have a point with maintenance problems. These complicated pipes can get almost as bad as they were written in perl :)
|
|
Kyle Brandt
|
Posted : Tue, 27 May 2008 17:51:28
Subject :
Re: Re: parsing config file via bash script
[quote=xi]Assuming the separator symbol is not part of any of the words, this also works:
[code=xml]cat file.lst | while read line ; do
echo "${line##*|}"
done[/code][/quote]
I like this solution, fyi it could also be written:
[code=xml]while read line; do
echo "${line##*|}"
done < file.lst[/code]
|
|
Khabi
|
Posted : Thu, 29 May 2008 22:46:56
Subject :
Re: parsing config file via bash script
[quote=Anthony Robbins]I must confess I love pipes but it's probably just me :)
For some reason I have a feeling that using dedicated binaries (eg. cut) is faster than awk especially if two sides of the pipe can run on a different CPUs. I often have to parse these neverending log files and it matters there. I might be completely wrong though, I mean, they can't run in parallel since one is connected to the other.
You definitely have a point with maintenance problems. These complicated pipes can get almost as bad as they were written in perl :)[/quote]
You know, that would be an interesting test. If you get a chance next you parse whatever it is your are to try running the time test against it and possibly try it again with awk I would be interested to see what the results are. :)
|
|
asmerm
|
Posted : Tue, 03 June 2008 10:43:29
Subject :
parsing config file via bash script
wow! This became discussion! cut is also very easy to use for beginners like me!
|
|
AR
|
Posted : Wed, 25 June 2008 20:56:46
Subject :
Re: Re: Re: parsing config file via bash script
I've run some tests a couple of times on a 14MB text file consisting of pwgen's output like
Yee2Aith Kaibo9ku oY2Ipe3y iPah9ieg zoo3oNg1 Pa3phae6 Caatho8a Ush5ohTe
thahth6S yeep3Phi ounee5Ei eopeik4S goi1Aiye quo8iZes Aewie0Xu AeZae0ia
phee5Ahw Too1uaR0 taem9ieP ShiY2eek sie8eeZ0 auNg7hie iich0Oom cohQu9Uu
...
# cut -f3,5 -d\ big2.txt > /dev/null
average: 0.13s
# awk '{print $3" "$5}' big2.txt>/dev/null
average: 0.27s (128% of cut|tr)
awk actually does more (it skips multiple field separators while cut does not)
so to achieve the exact same effect the correct command line would be
# tr -s \ < big2.txt | cut -f3,5 -d\ > /dev/null
average: 0.21s (100%)
since this is a semi-SMP system (3ghz p4 HT) I've run the last
two tests (awk vs. tr | cut) on a mono processor computer (2.4ghz p4) on the same file:
# awk '{print $3" "$5}' big2.txt > /dev/null
average: 0.38s (135%)
# tr -s \ < big2.txt | cut -f3,5 -d\ > /dev/null
average: 0.28s (100%)
The bottom line is that cut is way faster, cut | tr is still faster than awk
and it's interesting to see that HT-SMP did not help at all (tr | cut was relatively
slower on HT). All the computers were running the same kernel/os (2.6,debian etch)
edit:
I've managed to get my hands on a 8 CPU system and increased the file size to 10x
# awk '{print $3" "$5}' big3.txt>/dev/null
average: 2.35s (189%)
# tr -s \ < big3.txt | cut -f3,5 -d\ > /dev/null
average: 1.24s (100%)
looks like real SMP helps and filters with pipes in them scale a lot better :)
[Modified by: Anthony Robbins on June 25, 2008 09:16 PM]
|
|
Khabi
|
Posted : Thu, 26 June 2008 19:36:31
Subject :
Re: parsing config file via bash script
Anthony,
I'm actually surprised that the difference was that much, I would have figured it would have been smaller if any difference at all. I'm guessing its the overhead from awk's ability to do formatted output or something.
|