LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices



Reply
 
Search this Thread
Old 05-04-2005, 05:50 PM   #1
senorsnor
Member
 
Registered: Apr 2004
Location: Delft, Netherlands
Distribution: ArchLinux
Posts: 46

Rep: Reputation: 15
[Bash] Concatenate string using awk


I'm writing a bash-script to put the free disk space of my four harddisks into rrd-tool. Therefore, I want to create a string that holds the free disk space of all the disks, seperated by a colon so it will be like :36453:34523:84726:72639. So I came up with the following script:

#!/bin/sh

DISKS="hda1 hda5 hdb1 hdd1"
UPDATESTRING=""

for i in $DISKS; do
df | grep $i | awk '{ UPDATESTRING=$UPDATESTRING":"$4 }'
done

echo $UPDATESTRING

But that doesn't work, nothing happens with the UPDATESTRING. So I wonder what I'm doing wrong? Anyone can help me?
 
Old 05-04-2005, 05:59 PM   #2
Tinkster
Moderator
 
Registered: Apr 2002
Location: in a fallen world
Distribution: slackware by choice, others too :} ... android.
Posts: 23,005
Blog Entries: 11

Rep: Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903
Re: [Bash] Concatenate string using awk

Code:
 df -k | awk '{if( $0 ~ "/dev/" ) USTRING=USTRING":"$4} END{print USTRING}'

Cheers,
Tink
 
Old 05-04-2005, 06:13 PM   #3
senorsnor
Member
 
Registered: Apr 2004
Location: Delft, Netherlands
Distribution: ArchLinux
Posts: 46

Original Poster
Rep: Reputation: 15
Thanks! Now I'm getting some output here :-P

It isn't exactly what I was looking for, however: Now the values appear with the colons in front of it, but they're all on seperate lines, and after the awk, the variable UPDATESTRING (or USTRING as you named it) is empty. The output I get is

:920516
:58966700
:3847316
:19530372
<<< this is an empty line

So if you take my first code, you see in the beginning I declare the variable UPDATESTRING as an empty string, then in the awk I add these values to it, but only the value from the current iteration of the for-loop is printed to the screen. After the awk, the UPDATESTRING is printed again, but now it is empty again.

So it seems to be that the variable I declare within the body of awk (so to speak) is only visible when this awk is being executed, but after the awk has finished, the variable is gone too?
 
Old 05-04-2005, 06:28 PM   #4
senorsnor
Member
 
Registered: Apr 2004
Location: Delft, Netherlands
Distribution: ArchLinux
Posts: 46

Original Poster
Rep: Reputation: 15
Allright, I found out something: using `awk -v var=value` it is possible to make a global variable visible within an awk-loop. So if I do

#!/bin/sh

DISKS="hda1 hda5 hdb1 hdd1"
UPDATESTRING="jajajja"

for i in $DISKS; do
df | grep $i | awk -v USTRING=$UPDATESTRING '{ USTRING=USTRING":"$4 } END {print USTRING }'
done

echo $UPDATESTRING

I get the output

jajajja:920516
jajajja:58966700
jajajja:3847316
jajajja:19530372
jajajja

So it seems now I need to find out how to put a value from within an awk-loop into a global variable ..
 
Old 05-04-2005, 07:09 PM   #5
jschiwal
Guru
 
Registered: Aug 2001
Location: Fargo, ND
Distribution: SuSE AMD64
Posts: 15,733

Rep: Reputation: 655Reputation: 655Reputation: 655Reputation: 655Reputation: 655Reputation: 655
Since you might be adding a drive in the future, perhaps you should rely on the pattern rather than using loop variables.

Something like this in sed may do the job. The trick is to encompass both the device pattern and the free space number in the search pattern, storing the parts that you need saved for the replacement string.
Code:
/bin/df | sed -n '/\/dev\/\(hd[a-g][[:digit:]][[:digit:]]*\) [^ ][^ ]*  [^ ][^ ]*  \([[:digit:]][[:digit:]]*\)$/s//\1:\2/p'
The \( ... \) stores the pattern that matches the regular expression for reuse in the replacement string. The \1 in the replacement string will be replaced with the first stored pattern, while the \2 will be replaced with the second. I could have had used [0-9] instead of [[:digit:]] in the pattern.

The computer I tried this on had df aliased to include the -h option, so it was tested with the pattern [[:digit:]\.KMGT]* instead of [[:digit:]][[:digit:]]*. So I added '/bin/' in the front so that the alias wouldn't be used.

On some systems, a device like /dev/hda1 might be a link to something like /dev/ide/host0/bus0/target0/part1 and so the original assumptions made about the patterns of the disk devices would be wrong
------

I have yet to learn using Awk. If you can use the same \( ... \) patterns in awk with \n in the print statement, you could use that instead of variables.

Also, since sed and awk statements begin with search patterns, piping the df output through grep is redundant.


P.S. to moderator: I had to check the spelling of octothorpe using dictionary.com. It came up as a spelling error (on the pre-edited version of this message).

Last edited by jschiwal; 05-04-2005 at 08:24 PM.
 
Old 05-04-2005, 08:21 PM   #6
Tinkster
Moderator
 
Registered: Apr 2002
Location: in a fallen world
Distribution: slackware by choice, others too :} ... android.
Posts: 23,005
Blog Entries: 11

Rep: Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903
Quote:
Originally posted by senorsnor
Thanks! Now I'm getting some output here :-P

It isn't exactly what I was looking for, however: Now the values appear with the colons in front of it, but they're all on seperate lines, and after the awk, the variable UPDATESTRING (or USTRING as you named it) is empty. The output I get is

:920516
:58966700
:3847316
:19530372
<<< this is an empty line

So if you take my first code, you see in the beginning I declare the variable UPDATESTRING as an empty string, then in the awk I add these values to it, but only the value from the current iteration of the for-loop is printed to the screen. After the awk, the UPDATESTRING is printed again, but now it is empty again.

So it seems to be that the variable I declare within the body of awk (so to speak) is only visible when this awk is being executed, but after the awk has finished, the variable is gone too?
Actually my one-liner replaces your entire script?



Cheers,
Tink
 
Old 05-04-2005, 08:58 PM   #7
Tinkster
Moderator
 
Registered: Apr 2002
Location: in a fallen world
Distribution: slackware by choice, others too :} ... android.
Posts: 23,005
Blog Entries: 11

Rep: Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903
Quote:
Originally posted by jschiwal
I have yet to learn using Awk. If you can use the same \( ... \) patterns in awk with \n in the print statement, you could use that instead of variables.
awk doesn't know about back-referencing, and quite
frankly I find it more readable without it ;)

Quote:
P.S. I had to check the spelling of octothorpe using dictionary.com. It came up as a spelling error (on the pre-edited version of this message).
I just call it the hash-key(sign) :)


Cheers,
Tink
 
Old 05-05-2005, 01:38 AM   #8
jschiwal
Guru
 
Registered: Aug 2001
Location: Fargo, ND
Distribution: SuSE AMD64
Posts: 15,733

Rep: Reputation: 655Reputation: 655Reputation: 655Reputation: 655Reputation: 655Reputation: 655
I agree that your awk version is much more readable. I hope that my main point about not needing a loop, selecting fixed device names makes a point. Your one-liner does the same.

I would use the term "pound". I believe that read line or the unicode standard uses the "octothorpe" term.

According to the linux-dictionary:
Common: number sign; pound; pound sign; hash; sharp; crunch;
hex; [mesh]. Rare: grid; crosshatch; octothorpe; flash; <square>, pig−pen; tictactoe; scratchmark;
thud; thump; splat.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Bash script question (grep and awk) hamish Linux - Software 6 04-06-2005 04:14 PM
PL/PGSQL - String concatenate problem jaunine Linux - Software 7 03-18-2005 08:11 AM
pass value from awk back to bash shell cjs_pro Programming 2 03-07-2005 05:53 PM
Bash: How to concatenate the output of different commands? J_Szucs Programming 1 11-13-2003 08:43 AM
string concatenation in AWK xanthium Programming 1 04-22-2002 05:41 AM


All times are GMT -5. The time now is 04:04 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration