Как я могу использовать значение из трубы в тестовой программе?

10
wc -l | test -eq 1

Это не работает Я хочу сравнить результат wc со значением 1. Как я могу это сделать?

tr3quart1sta
источник

Ответы:

9

Он не отвечает на ваш вопрос о каналах, но вы можете переставить:

test $(ls -l | wc -l) -eq 1 && echo "worked"

И есть несколько решений на SO , это самое хорошее:

ls -l | wc -l | { read wc; test $wc -eq 7 && echo "woohoo"; }
Оли
источник
4

Если вы используете Bash, вы, вероятно, захотите исследовать переменную PIPESTATUS. Как отмечено в справочном руководстве Bash , PIPESTATUS является

Переменная массива (см. Массивы), содержащая список значений состояния выхода из процессов в последнем выполненном конвейере переднего плана (который может содержать только одну команду).

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

dmesg | grep -iw 'nnse' | wc -l

Если вы теперь запросите переменную массива, вы получите статусы выхода, ссылающиеся на команды, используемые в конвейере:

echo ${PIPESTATUS[@]}
0 1 0

(В индексированном массиве эти коды выхода выше представлены в массиве 0 1 и 2, так как массивы всегда начинаются с 0 в Bash.)

Здесь мы видим, что вторая команда вернула 1, а остальные 0; однако wc -lвозвращает 0, если совпадений нет, что не является ошибкой. Отказ представлен ненулевым значением, и есть другие значения ошибок, такие как 127, команда не найдена, и еще больше кодов, которые могут быть специфическими для данной программы.

Если вы хотите увидеть, каким был код выхода конкретной команды в конвейере, вы можете просто получить доступ к этому значению. Команда grep была второй командой в конвейере выше, но так как массивы начинаются с 0, нам нужна первая запись.

Поэтому, чтобы узнать код завершения команды grep, снова запустите приведенный выше конвейер (так как содержимое PIPESTATUS будет исчерпано, если вы его запустили echo ${PIPESTATUS[@]}), а затем выполните приведенную ниже команду, которая вернет 1 (код выхода):

echo ${PIPESTATUS[1]}
1

В сценарии убедитесь, что конвейер завершил выполнение, прежде чем искать содержимое переменной массива PIPESTATUS.

Пример интересного использования переменной массива PIPESTATUS см. В этом ответе относительно объединения групп команд Bash и состояния канала . Вы можете проверить переменную массива способом, предложенным Жилем в комментариях, хотя сначала вам нужно будет снова запустить конвейер:

dmesg | grep -iw 'nnse' | wc -l
[ ${PIPESTATUS[1]} -eq 1 ] && do_something_here

Это всего лишь фрагмент, так как я не знаю, какой сценарий вы намереваетесь, но я надеюсь, что знание о PIPESTATUS может вам пригодиться. Существует много переменных массива Bash, таких как PIPESTATUS, которые могут быть чрезвычайно полезны; см. справочное руководство по Bash для всего списка и другие сайты Stackexchange для примеров их использования.

Сообщество
источник
2

Самый простой способ - использовать xargs :

wc -l | xargs -I % test % -eq 1
Джон Доу
источник
1

Это не покрывает каждый testслучай, но если вы можете использовать регулярное выражение и grepпереданную по конвейеру строку, это довольно просто, потому что grep- testпохоже на то, что оно имеет ненулевой выход, когда совпадение не найдено

cat file | wc -l | grep -qE '^\s*1\s*$'

Расширенные регулярные выражения позволяют вам охватить многие случаи с помощью этой техники. Для хихиканья, тестовый пример:

for i in 1 11 '' foo; do 
  if echo $i | grep -qE '^\s*1\s*$'; then 
    echo "'$i' matched"
  else
    echo "'$i' didn't match."
  fi
done

выходы:

'1' matched
'11' didn't match.
'' didn't match.
'foo' didn't match.
zanerock
источник