Почему я не могу группировать команды sed после адреса в блоке?

Ваш скрипт не делает то, что вы хотите, потому чтокогда timeout -t 10 commandимеет статус выхода 0 --, который является статусом выхода, который считается истинным в сценариях оболочки --, команда timeout -t 10 command || [ $? = 143 ]просто завершается со статусом выхода 0 и не вызывает право -сторона ||для запуска. Точно так же, если вы замените ||на &&, то любой ненулевой статус выхода из левой -стороны будет статусом выхода всей команды, а правая -сторона будет не быть запущенным.

Вы должны просто запустить их как две отдельные команды , разделив их ;или новой строкой. При необходимости вы все равно можете использовать их оба в качестве условия if, когда делаете это (, см. ниже ).

Я предполагаю, что вам нужен статус выхода timeout -t 10 command, а не command(, если он отличается от ). Иначе мне непонятно, чего вы хотите; , как и ilkkachu , я не знаком с командой timeout, которая принимает параметр -t. Обычно я бы предложил вам сделать это таким образом, за исключением того, что это звучит так, как будто ваше «внешнее ограничение» может запретить это, поскольку оно вообще не использует if:

timeout -t 10 command
test "$?" -eq 143
exit

Команда test/ [возвращает код выхода 0, чтобы указать true, и 1, чтобы указать false, поэтому вам не нужно писать отдельные ветки с exit 0и exit 1. Встроенная команда exitпри запуске без аргументов заставляет оболочку возвращать статус выхода последней выполненной команды.

Если вы уже находитесь в конце скрипта, то вы можете опустить exit, потому что когда управление перетекает из конца скрипта, это имеет тот же эффект, что иexit:

timeout -t 10 command
test "$?" -eq 143

(В любом случае вы можете написать [ "$?" -eq 143 ]вместо test "$?" -eq 143, если хотите. Подробнее об использовании [/ testсм. ниже.)

Хотя ваше описание звучит так, будто вы не можете использовать этот код в точности, вы, тем не менее, должны быть в состоянии изменить его, чтобы он принял требуемую форму.Вы сказали, что должны не только выполнить проверку , но также запустить команду в предложении if. Это, по-видимому, запрещает удобочитаемый и идиоматический подход, предложенный Хауке Лагингом запуска команды перед if.

Так что, если вы не можете этого сделать, вы можете включить команду в условие if, как вы это делали, но отделить ее от вашей команды test/ [с помощью ;, а не||:

if timeout -t 10 command; [ "$?" -eq 143 ]; then
    exit 0
else
    exit 1
fi

(Вы можете обойтись без""вокруг $?. Вы также можете написать =вместо 143, хотя это сбивает с толку, потому что =означает текстовое, а не числовое сравнение. Вы можете написать test "$?" -eq 143вместо [ "$?" -eq 143 ], если хотите.)

Причина, по которой это работает, заключается в том, что вам разрешено писать ifусловие, состоящее из нескольких команд, разделенных точкой с запятой или даже новой строкой. Вот почему грамматика оболочки требует, чтобы вы писали then, чтобы указать конец условия if. Поэтому вам не нужно пытаться обходным путем использовать оператор &&или ||, когда ваша цель состоит в том, чтобы запустить две команды в качестве условия if, заставляя ifсамостоятельно проверять только вторую.

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

10
04.12.2019, 21:21
2 ответа

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

sed -n '/PATTERN/q; p;' file

Здесь вывод пространства шаблонов по умолчанию в конце каждого цикла отключен с помощью -n. Вместо этого мы явно выводим каждую строку с p. Если данный шаблон совпадает, мы останавливаем обработку с помощью q.

Ваша фактическая, более длинная команда, которая изменяет имя хромосомы 21 с простого 21на chr21в первой строке файла fasta, а затем продолжает извлекать ДНК для этой хромосомы, пока не дойдет до следующей. строка заголовка fasta, может быть записана как

sed -n -e '1 { s/^>21/>chr21/p; d; }' \
       -e '/^>/q' \
       -e p <in.fasta >out.fasta

или

sed -n '1 { s/^>21/>chr21/p; d; }; /^>/q; p' <in.fasta >out.fasta

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

Обратите внимание, что для синтаксической корректности в системах, отличных от -GNU, исходный сценарий должен выглядеть как /PATTERN/ { d; q; }. Обратите внимание на добавленный ;послеq(пробелы не имеют значения ).

14
27.01.2020, 20:00

Вы можете получить тот же вывод (, только те строки, которые предшествуют первому совпадению ), используя две формы адреса -:

sed -e '/PATTERN/,$d'

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

1
27.01.2020, 20:00

Теги

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