Парсинг параметров командной строки процесса от pargs в сценарии оболочки

Более простой путь состоял бы в том, чтобы использовать a case оператор вместо проверки $? неоднократно:

case "$?" in
    0) echo "Password successfully changed on $host by $user" ;;
    1) echo "Failure, password unchanged" ;;
    2) echo "Failure, new and old passwords are too similar" ;;
    3) echo "Failure, password must be longer" ;;
    *) echo "Password failed to change on $host" ;;
esac
3
22.03.2014, 00:28
4 ответа

Как выглядит вывод команды pargs -l $ PID ? Из вашего кода кажется, что это одна строка, содержащая все аргументы командной строки в формате, например:

arg1=val1 arg2=val2

Если да, вы можете получить значение для аргумента -DnodeId с помощью ] sed команда:

$ ARGS="-DfirstArg=foo -DanotherArg=bar -DnodeId=1234 -DlastArg=baz"
$ echo "$ARGS" | sed -r 's/.*-DnodeId=([^ ]+).*/\1/g'
1234

Таким образом, ваш сценарий может выглядеть так:

PARGS=$(pargs -l $PID)
NODE='UNKNOWN'
if [ -n "$(grep "DnodeId" <(echo "$PARGS"))" ]; then
    NODE=$(echo "$PARGS" | sed -r 's/.*-DnodeId=([^ ]+).*/\1/g')
fi
1
27.01.2020, 21:20

Если все, что вас волнует, это то, что идет справа от = , если то, что слева, - -DnodeId , вы можете сделать это:

NODE=$(pargs -l $PID| awk -F '-DnodeId=' '{sub(" .*","",$2);print $2}')

Это напечатает все, что идет справа от шаблона -DnodeId = , вплоть до первого пробела, но исключая его. Если в командной строке более одного -DnodeId , он будет работать только с первым.

Также возможно обрабатывать более одного -DnodeId в строке:

NODES=($(pargs -l $PID| awk -F '-DnodeId=' '{
          for(i=2;i<=NF;i++){
              sub(" .*","",$i);
              print $i
          }
        }'
))
1
27.01.2020, 21:20

Кажется, что то, что вы делаете, определенно будет очень медленным, поскольку каждый раз, когда вы var = $ (command substitute) , вы должны останавливаться и ждать его вывода, прежде чем переходить к следующему шагу. Готов поспорить, что вы бы подождали гораздо меньше, если бы просто обработали его в потоке с помощью sed, редактора потока :

NODE="$(pargs -l $PID | sed -rn '/(-DnodeId)=(\S*)/{s//\2/pq}')"

Я не совсем уверен насчет одинарных кавычек - Я только что набрал это на своем телефоне, но функция sed y определенно справится с этим, если она вам все еще нужна.

Выше Джош демонстрирует неудачный случай. Вероятно, было бы намного проще просто добавить:

${NODE:?PID not found...quitting}

После выполнения вышеуказанной команды sed .

Мне приходит в голову, что они не обязательно уже разделены строкой, мы можем справиться с этим достаточно легко с помощью еще 1 | pipe - все еще в одном потоке данных, а также с учетом возможности нескольких совпадений :

. <<PIDSED /dev/stdin
    $(pargs -l $PID |\
        sed -rn 's/(-DnodeId)=(\S*)/\
            echo "NODE$((i=i+1))=\2" ;/gp' |\
        . /dev/stdin)
PIDSED
1
27.01.2020, 21:20

Обрабатывайте аргументы с помощью bash, а не внешних процессов

for ARG in "${PARGS_ARR[@]}"
do
  # trim single quotes 
  ARG=${ARG//\'}

  # split by equals sign
  IFS="=" read ARGL ARGR <<< "$ARG"

  if [[ "$ARGL" == "-DnodeId" ]]; then
    NODE=$ARGR
  fi
done
1
27.01.2020, 21:20

Теги

Похожие вопросы