0

I have the following output returned by awk:

qh1adm 20130711151154 : tp import all QH1 u6 -Dsourcesystems=BFI,EBJ
qh1adm 20130711151155 : tp import all QH1 u6 -Dsourcesystems=E7B,B17  
qh1adm 20130711151200 : tp import all QH1 u6 -Dsourcesystems=BFI,EBJ

I want to store this in an array in-order to count the number of records. If it is more than 1 only then I want to display the contents of this array. Can you please assist?

Thanks a lot.

5 Answers 5

1

Using bash/zsh, capture the output, count the lines, and print it if it meets your criteria:

output=$(awk 'something that returns what you showed in your question')
nlines=$(wc -l <<< "$output")
if ((nlines > 1)); then
    echo "$output"
fi
Sign up to request clarification or add additional context in comments.

1 Comment

+1 for disregarding what the OP asked for and just giving him what he needed instead :-)!
1
awk '{s[c++]=$0} END { if (c>1) { for (c in s) { print s[c]; } } }'

3 Comments

Hello Karoly, Thanks for your reply. So would it be something like this: awkcommand '{s[c++]=$0} END { if (c>1) { for (c in s) { print s[c]; } } }'
P.S. Sorry I am still trying to figure out the corrct the correct way to insert line breaks and preformatted texts.
I don't understand either of those questions, you have to be a lot more specific. I don't know what's your awk script so I don't know how to combine the two... but you could just yourawkcommand | awk ....
1
... | awk 'NR == 1 {first=$0} NR == 2 {print first} NR > 1 {print}'

This will output nothing if there are 1 or fewer lines in the input. Otherwise it prints the entire input. It's efficient because it stores only the first line, so it does not waste memory on storing the entire input in an array.

Comments

0

You could just store the output of awk in a file and then count the lines of the file.

TEMP_FILE=`mktemp`
awk_command > $TEMP_FILE
if [[ `wc -l < $TEMP_FILE` -gt 1 ]]
then
  cat $TEMP_FILE
fi
rm $TEMP_FILE

1 Comment

Hello beny, thanks for the code. I plugged in the above and it worked perfectly! Thank you very much for your help.
0

In case anyone in future is reading this and wondering how to actually get multi-line awk output into a bash array:

$ cat ./tst.sh
# ensure globbing is off and set IFS to a newline after saving original values
oSET="$-"; set -f; oIFS="$IFS"; IFS=$'\n'

array=( $(
    awk 'BEGIN{
        print "qh1adm 20130711151154 : tp import all QH1 u6 -Dsourcesystems=BFI,EBJ"
        print "qh1adm 20130711151155 : tp import all QH1 u6 -Dsourcesystems=E7B,B17"
        print "qh1adm 20130711151200 : tp import all QH1 u6 -Dsourcesystems=BFI,EBJ"
    }'
) )

# restore original IFS and globbing values
IFS="$oIFS"; set +f -"$oSET"

numElts="${#array[@]}"

if (( numElts > 1 ))
then
    for (( i=0; i < numElts; i++ ));
    do
        printf "array[%d]: %s\n" "$i" "${array[$i]}"
    done
fi
$
$ ./tst.sh tmp
array[0]: qh1adm 20130711151154 : tp import all QH1 u6 -Dsourcesystems=BFI,EBJ
array[1]: qh1adm 20130711151155 : tp import all QH1 u6 -Dsourcesystems=E7B,B17
array[2]: qh1adm 20130711151200 : tp import all QH1 u6 -Dsourcesystems=BFI,EBJ

but apparently none of that is actually necessary in this case and the whole thing should probably just be done within the one awk command.

The above has been updated to address issues raised by and input from @CharlesDuffy below.

7 Comments

This isn't actually safe: array=( $(stuff) ) does string-splitting and glob expansion on the output of stuff, making it hard to guarantee that results come back exactly the way you want them. A safer approach would be to have awk emit NUL-delimited entries, and to use array=(); while read -r -d ''; do array+=( "$REPLY" ); done < <(awk ...) to read them in.
...to be a bit more explicit -- let's say you had a line containing only * in the output from awk; it would be replaced with a list of files in the current directory before being put into array.
You're right about the glob expansion being an issue. Could you give an example of when string-splitting would be an issue? I REALLY would hate to have to write that loop you suggested just to populate the array, I'd rather just state glob expansion as a caveat. Do you have any other suggestions other than escaping every glob metacharacter in the prints.
The other option is to use set -f to disable globbing, and set +f to reenable it later. That's somewhat bad form for the same reason changing IFS is (without explicitly scoping that IFS change to a single command, as done by IFS=... read) -- you're increasing the amount of context someone needs to have in their head to understand what a given piece of script does.
I don't want to do a set -f in case it was disabled earlier if this segment was used in the middle of a larger script but I can save the value of $- before the set -f and restore it later. Obviously I can also save IFS and restore that to it's original value later too. Let me update the script now then please take another look and see if there's anything else. How about word-splitting, is that really an issue in this case?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.