Почему делает (выйдите 1), не выходят из сценария?

С GNU awk Вы может установить RS к содержанию скобок и затем делают замену на RT (подобранный разделитель записей):

awk -v RS='\\[[^]]*\\]' '{ gsub(/\<(BAR|WIBBLE|ME)\>/, "FOO", RT); printf "%s%s", $0, RT }' infile

infile:

cat << EOF > infile
SHE GAVE ME THAT
SOMETHING [ME, WIBBLE, SOMMER]
EOF

вывод:

SHE GAVE ME THAT
SOMETHING [FOO, FOO, SOMMER]
49
13.12.2017, 19:46
3 ответа

() выполняет команды в подоболочке, поэтому с помощью exit вы выходите из подоболочки и возвращаетесь в родительскую оболочку. Используйте скобки {}, если хотите выполнять команды в текущем shell'е.

Из bash manual:

(list) список выполняется в окружении подоболочки. Назначения переменных и команды сборки, влияющие на окружение оболочки, не остаются в силе после завершения команды. Статус возврата - это статус выхода из списка. Список

{ list; } просто выполняется в текущем окружении оболочки. Список должен быть завершён новой строкой или точкой с запятой. Это известно как групповая команда. Статус возврата - это статус выхода из списка. Обратите внимание, что в отличие от метасимволов ( и ), { и } являются зарезервированными словами и должны встречаться там, где зарезервированное слово разрешено к распознаванию. Поскольку они не вызывают разрыв слова, они должны быть отделены от списка пробелами или другими метахарическими символами оболочки.

Стоит упомянуть, что синтаксис оболочки достаточно последователен и подоболочка также участвует в других () конструкциях, таких как подстановка команд (также в старом стиле `...`...`...}. ` синтаксис) или подстановка процессов, поэтому из текущей оболочки тоже не выйдет:

echo $(exit)
cat <(exit)

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

  • команда, запущенная в фоновом режиме

    выходит &
    

    не выходит из текущей оболочки, потому что (после man bash)

    Если команда завершается оператором управления и оболочка выполняет команду в фоновом режиме в подоболочке. Оболочка не ждет завершения команды, а возвращает статус 0.

  • pipeline

     exit | echo foo
    

    до сих пор выходит только из подсхемы.

    Однако различные оболочки ведут себя по-разному в этом отношении. Например, bash помещает все компоненты трубопровода в отдельные оболочки (если только Вы не используете опцию lastpipe в вызовах, где управление заданием не включено), но AT&T ksh и zsh запускают последнюю часть внутри текущей оболочки (оба поведения разрешены POSIX). Таким образом

    выход | выход | выход
    

    практически ничего не делает в бэше, но выходит из zsh из-за последнего выхода .

  • выход coproc также работает выход в подсхеме.

87
27.01.2020, 19:33

Поскольку вы не указали дистрибутив, я опишу метод Ubuntu (и, возможно, его производные) Попробуйте найти папки $ HOME/.Private и $ HOME/.ecryptfs . Должен присутствовать любой из них или оба. или попробуйте ls -A/home , чтобы получить выходные данные с упоминанием одной или обеих папок.

Источник: EncryptedHome - справка Ubuntu Wiki

-121--83238-

Из меньше введите s , затем введите имя файла, в который требуется сохранить файл, затем введите .
На странице man в разделе COMMANDS :

s filename
      Save the input to a file.  This only works if the input is a pipe, not an ordinary file.

man также указывается, что в зависимости от конкретной установки команда s может быть недоступна. В этом случае можно перейти к строке 1 с:

g or < or ESC-<
      Go to line N in the file, default 1 (beginning of file).

и направить весь контент к cat с:

| <m> shell-command
      <m> represents any mark letter. Pipes a section of the input file to the
      given shell command. The section of the file to be piped is between the
      first line on the current screen and the position marked by the letter. 
      <m> may also be ^ or $ to indicate beginning or end of file respectively.

, так что либо:

g|$cat > filename

, либо:

<|$cat > filename

т. е. введите g или < ( g или меньше ) | $ ( труба , затем доллар ), затем cat > имя файла и введите .
Это должно работать независимо от того, является ли входной файл каналом или обычным файлом.

-121--4832-

Выполнение exit в субоболочке представляет собой один недостаток:

#!/bin/bash
function calc { echo 42; exit 1; }
echo $(calc)

Сценарий печатает 42, выходит из субоболочки с кодом возврата 1 и продолжает сценарий. Даже замена вызова на echo $ (CALC) | | exit 1 не помогает, поскольку код возврата echo 0 независимо от кода возврата calc . И расчет выполняется до эхо .

Еще больше недоумения мешает эффекту exit , заключив его в локальный builtin, как в следующем сценарии. Я наткнулся на проблему, когда написал функцию для проверки входного значения. Пример:

Я хочу создать файл с именем «year month day.log», то есть 20141211 log на сегодня. Дата вводится пользователем, который может не предоставить разумное значение. Поэтому в моей функции fname я проверяю возвращаемое значение date , чтобы проверить действительность пользовательского ввода:

#!/bin/bash

doit ()
    {
    local FNAME=$(fname "$1") || exit 1
    touch "${FNAME}"
    }

fname ()
    {
    date +"%Y%m%d.log" -d"$1" 2>/dev/null
    if [ "$?" != 0 ] ; then
        echo "fname reports \"Illegal Date\"" >&2
        exit 1
    fi
    }

doit "$1"

Выглядит хорошо. Разрешить скрипту имя s.sh . Если пользователь вызывает скрипт с помощью ./s.sh «Thu Dec 11 20:45:49 CET 2014» , создается файл 20141211 log . Если, однако, пользователь вводит ./s.sh «Thu hec 11 20:45:49 CET 2014» , то сценарий выводит:

fname reports "Illegal Date"
touch: cannot touch ‘’: No such file or directory

Строка fname... говорит, что в оболочке обнаружены плохие входные данные. Но exit 1 в конце строки local... никогда не запускается, поскольку директива local всегда возвращает 0 . Это происходит потому, что локальный выполняется после $ (fname) и, таким образом, перезаписывает его код возврата. И поэтому сценарий продолжается и вызывает touch с пустым параметром. Этот пример прост, но поведение bash может быть довольно запутанным в реальном применении. Знаю, настоящие программисты не используют locals.☺

To дают понять: Без локального сценарий прерывается так, как ожидалось, когда вводится недопустимая дата.

Исправление состоит в том, чтобы разделить строку, как

local FNAME
FNAME=$(fname "$1") || exit 1

Странное поведение соответствует документации local в пределах man-страницы bash: «Возвращаемое состояние 0, если локальное не используется вне функции, указано недопустимое имя или имя является переменной только для чтения».

Хотя не является ошибкой, я чувствую, что поведение bash является контринтуитивным. Я знаю о последовательности выполнения, локальный не должен маскировать нарушенное назначение, тем не менее.

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

13
27.01.2020, 19:33

Скобки запускают подоболочку , и выход только из этой подоболочки.

Вы можете прочитать код выхода с помощью $? и добавить его в свой скрипт, чтобы выйти из скрипта, если подоболочка была закрыта:

#!/bin/bash

function bla() {
    return 1
}

bla || ( echo '1' ; exit 1 )

exitcode=$?
if [ $exitcode != 0 ]; then exit $exitcode; fi

echo '2'
1
27.01.2020, 19:33

Теги

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