LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   [Bash] Concatenate string using awk (https://www.linuxquestions.org/questions/programming-9/%5Bbash%5D-concatenate-string-using-awk-320173/)

senorsnor 05-04-2005 05:50 PM

[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?

Tinkster 05-04-2005 05:59 PM

Re: [Bash] Concatenate string using awk
 
Code:

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

Cheers,
Tink

senorsnor 05-04-2005 06:13 PM

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?

senorsnor 05-04-2005 06:28 PM

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 ..

jschiwal 05-04-2005 07:09 PM

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).

Tinkster 05-04-2005 08:21 PM

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

Tinkster 05-04-2005 08:58 PM

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

jschiwal 05-05-2005 01:38 AM

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.


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