2014-10-24 2 views
1

Вот мой сценарийGot код выхода 123 в находке + xargs Grep

eval "find \\(-type f -a \\(-name '*.h' \\) \\) -print0" | xargs -0 -n100 grep -f <(echo "stdio") 
echo $? 

Ничего не найдено, и код завершения 123.

Если я изменить его немного следующим

echo "stdio" >.P 
eval "find \\(-type f -a \\(-name '*.h' \\) \\) -print0" | xargs -0 -n100 grep <.P 
echo $? 

Что-то найдено, но код выхода по-прежнему 123.

Итак, что не так?

================================================================================================================================== ===================================

На самом деле я просто хочу написать небольшой скрипт, чтобы упростить поиск + xargs + grep. Для exmaple,
xgrep -e -e ТЕСТ1 ТЕСТ2 ... * .c * .h
является выполнение
найти -name * .c -o -name * .h | xargs Grep -f < (эхо " $ PATTEN1 $ PATTERN2 ")

Используйте -f вместо -e, чтобы избежать неприятностей в экранировании одиночных или двойных кодов внутри шаблонов.

#!/bin/bash 
#set -e -o pipefail 

eval ARGV=($(getopt -l '' -o 'e:li' -- "[email protected]")) || exit 1 
for((i=0;i<${#ARGV[@]};i++)) { 
    o="${ARGV[$i]}" 
    case $o in 
    -e) 
     i=$((i+1)); 
     a="${ARGV[$i]}" 
     if [ -n "$grep_patterns" ]; then 
      grep_patterns="$grep_patterns"$'\n' 
     fi 
     grep_patterns="$grep_patterns$a" 
     ;; 
    -i) 
     grep_options="$grep_options -i" 
     ;; 
    -l) 
     grep_options="$grep_options -l" 
     ;; 
    --) 
     i=$((i+1)); 
     break;; 
    esac 
} 

for((;i<${#ARGV[@]};i++)) { 
    if [ -n "$find_options" ]; then 
     find_options="$find_options -o " 
    fi 
    find_options="${find_options}-name '${ARGV[$i]}'" 
} 

cmd="find \\(-type f -a \\($find_options \\) \\) -print0" 
eval "$cmd" | xargs -0 grep $grep_options -f <(echo "$grep_patterns") 
+3

Почему вы используете 'eval' здесь? –

ответ

2

123 означает «любой вызов, завершенный с ненулевым статусом». Таким образом, xargs выполнил grep не менее двух раз (потому что вы загрузили так много файлов, что они превысят максимальную длину командной строки, которую вы ограничили до 100 файлов), и по крайней мере одно из этих вызовов было в наборе файлов, которые не содержали совпадений, из-за чего код выхода от grep был отличным от нуля (сбой).

Возможно, вам стоит объяснить, что вы пытаетесь выполнить. eval выглядит излишним, и двойное перенаправление, вероятно, не выполняет то, что вы хотите (стандартный входной сигнал grep не может быть одновременно подключен к трубе от eval и до .P).

Если вы хотите параметризуем первый аргумент grep, может сделать что-то вроде

#!/bin/sh 
find -type f -name '*.h' -print0 | 
xargs -0 -n100 grep "$1" 

... где вы запускаете это, например, с stdio как первый аргумент.

(Обратите внимание также много упрощенных параметров к find. У вас есть только два предиката, так что нет необходимости в скобках ничего, а затем -a может быть отброшена, тоже.)

код выхода все равно будет 123 если есть grep invocations, которые возвращают нулевые совпадения. Вы можете уменьшить шансы, опуская -n 100 (что вряд ли, похоже, будет служить любому полезному куколку в любом случае), но если вы хотите полностью его предотвратить, вы можете пропитать весь трубопровод до | grep ., который сообщит об успехе, если бы был какой-либо выход. (Или вы можете запустить xargs на обертке, которая всегда возвращает успех, если код выхода от grep равен 0 или 1, но это сложнее, и вы увидите «успех» даже в случае совпадений нуля.)

1

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

Ваш сценарий, к сожалению, классический пример проблемы, описанной в http://mywiki.wooledge.org/BashFAQ/050: «Я пытаюсь поставить свою команду в переменной, но» ...

Короткая версия «не делать» , Длительная версия - это попытка использовать массивы и избегать переменных, где они не являются абсолютно необходимыми. Вот попытка рефакторинга вашего инструмента вдоль этих строк.

#!/bin/bash 
#set -e -o pipefail 

grep_patterns=() 
grep_options=() 

eval ARGV=($(getopt -l '' -o 'e:li' -- "[email protected]")) || exit 1 
for((i=0;i<${#ARGV[@]};i++)) { 
    case ${ARGV[$i]} in 
    -e) i=$((i+1)) 
     grep_patterns+=("-e" "${ARGV[$i]}") ;; 
    -i | -l) 
     grep_options+=("${ARGV[$i]}") ;; 
    --) i=$((i+1)); 
     break;; 
    esac 
} 

find_options=("${ARGV[@]:$i}") 

find -type f -a \("${find_options[@]}" \) -print0 | 
xargs -0 grep "${grep_options[@]}" "${grep_patterns[@]}" 

Я не уверен, передавая мультипликатор -e опции для grep поддерживается везде, но он отлично работает с GNU grep и упрощает вещи, на мой взгляд.

+0

Использование массивов является хорошим решением в этом случае. –

 Смежные вопросы

  • Нет связанных вопросов^_^