0

I have the following code snippet:

#!/bin/bash
clear
echo "PS to AWK"

read prg

check=($(ps -e | grep $prg | awk '{print "kILL " $4" "$1 " ? [y/n]"}'))

echo "${check[@]}"

The assumed output should be:

PS to AWK
auda
kILL audacious 2423 ? [y/n]

But unfortunately my output looks like this:

PS to AWK
auda
kILL audacious 2423 d i [y/n]

Someone has a hint why the question mark is lost and where the "d" and "i" are resulting from?

Thanks in advance for your answers.

John Goofy
  • 1,190
  • 1
  • 9
  • 19

2 Answers2

2

Instead of populating your shell array check using output from command substitution (which is subjected to glob expansion and word spitting) you should use read with process substitution like this:

read -ra check < <(ps -e | awk -v p="$prg" '$0 ~ p{print "kILL " $4" "$1 " ? [y/n]"}')

Then examine the result using:

echo "${check[@]}"

# or
declare -p check
anubhava
  • 713,503
  • 59
  • 514
  • 593
  • 1
    anubhava: Thank you, this works perfect for me, and checking an array with `declare` is really very helpfull. – John Goofy Mar 26 '17 at 17:40
1

The unquoted ? is expanded as a wildcard by the shell. You have two files with single-character names in the current directory.

The fix is to generally quote everything, unless you specifically require the shell to perform wildcard expansion and whitespace tokenization on a value.

The wildcard gets expanded in the array assignment, so you could quote that:

check=("$(ps -e | awk -v prg="$prg" '$0 ~ prg {print "kILL " $4" "$1 " ? [y/n]"}')")

but then you might was well not use an array. But then you might as well just capture the PID.

pid=$(ps -e | awk -v prg="$prg" '$0 ~ prg { print $1 }')

This loses the process name, though. You could refactor the script to print just the machine-readable parts, and then use those in a print statement.

check=($(ps -e | awk -v prg="$prg" '$0 ~ prg { print $1, $4 }'))
read -p "kILL ${check[1]} ${check[0]}? [y/n]"

(Incidentally, aligning the question mark with the previous word, as is the convention in English orthography, would also fix your problem, though sort of accidentally. Notice also how to avoid the useless use of grep in the examples above.)

tripleee
  • 158,107
  • 27
  • 234
  • 292
  • If I quote the question mark like this `check=($(ps -e | grep $prg | awk '{print "kILL " $4" "$1 " \? [y/n]"}'))` I only get an additional warning and there is still no `?`in my output. – John Goofy Mar 26 '17 at 17:18
  • Awk processes and removes the backslash so it's no longer there by the time the shell evaluates the output from Awk. I would just print the PID from Awk and defer the string formatting to the final `echo` (or perhaps `read -p` if you are going to be reading user input anyway). – tripleee Mar 26 '17 at 17:24