Способ использовать '/usr/bin/env sed-f 'в хижине?

Как @Steven говорит D, не забывайте info страницы.

Кроме того, не запугивайтесь info страницы. Я знаю много людей, которые не используют информационные страницы из-за встроенной системы навигации. Мое любимое решение состоит в том, чтобы передать информацию по каналу, пролистывает less:

info gpg |less

Таким образом, я могу перейти info страницы с помощью моего любимого пейджера. info страницы будут теперь вести себя то же как man страницы.

26
13.06.2011, 09:59
6 ответов

Вы не можете, портативно, поместить больше чем один аргумент на a #! строка. Это означает только полный путь и один аргумент (например. #!/bin/sed -f или #!/usr/bin/sed -f), или #!/usr/bin/env и никакой аргумент интерпретатору.

Обходное решение для получения портативного сценария должно использовать #!/bin/sh и обертка оболочки, передавая sed сценарий как параметр командной строки. Обратите внимание, что это не санкционировано POSIX (сценарии мультиинструкции должны быть записаны с отдельным -e аргумент в пользу каждой инструкции для мобильности), но это работает со многими реализациями.

#!/bin/sh
exec sed '
s/a/b/
' "$@"

Для длинного сценария может быть более удобно использовать heredoc. Преимущество heredoc состоит в том, что Вы не должны заключать одинарные кавычки в кавычки внутри, если таковые имеются. Главная оборотная сторона - то, что сценарий питается к sed на его стандартном входе с двумя раздражающими последствиями. Некоторые версии sed требуют -f /dev/stdin вместо -f -, который является проблемой для мобильности. Хуже, сценарий не может действовать как фильтр, потому что стандартный вход является сценарием и не может быть данными.

#!/bin/sh
exec sed -f - -- "$@" <<'EOF'
s/a/b/
EOF

Оборотная сторона heredoc может быть исправлена полезным использованием cat. Так как это помещает целый сценарий на командную строку снова, это не совместимо POSIX, но в основном портативно на практике.

#!/bin/sh
exec sed "$(cat <<'EOF')" -- "$@"
s/a/b/
EOF

Другое обходное решение должно записать сценарий, который может быть проанализирован и sh и sed. Это портативно, довольно эффективно, просто немного ужасно.

#! /bin/sh
b ()
{
x
}
i\
f true; then exec sed -f "$0" "$@"; fi
: ()
# sed script starts here
s/a/b/

Объяснения:

  • Под sh: определите вызванную функцию b; содержание не имеет значения, пока функция синтаксически правильно построена (в частности, у Вас не может быть пустой функции). Затем, если верный (т.е. всегда), выполниться sed на сценарии.
  • Под sed: перейдите к () маркировка, затем некоторый правильно построенный вход. Затем i команда, которая не имеет никакого эффекта, потому что она всегда пропускается. Наконец () маркировка, сопровождаемая полезной частью сценария.
  • Протестированный под GNU sed, BusyBox и OpenBSD. (Можно сойти с рук что-то более простое на GNU sed, но OpenBSD sed требователен в отношении частей, которые это пропускает.)
34
27.01.2020, 19:39
  • 1
    "или #!/usr/bin/env и никакой аргумент". не формулируется очень хорошо. Возможно, "или #!/usr/bin/env sed и никакой аргумент sed". –  cjm 13.06.2011, 12:03
  • 2
    +1 для "просто немного ужасного" и сценарий :) –  retracile 08.05.2012, 21:42

Существуют различные несовместимые реализации хижины (#!) в зависимости от ОС. Некоторые создают полный список аргументов, некоторые сохраняют путь команды и помещают все остающиеся аргументы как единственный, некоторые игнорируют все аргументы и передают только путь команды, и наконец, некоторые передают целую строку как единственную команду. Вы, кажется, находитесь в последнем случае.

6
27.01.2020, 19:39

ENV пытается найти файл с именем "sed-f". Можно попробовать "#!/usr/bin/sed-f" как строка хижины.

2
27.01.2020, 19:39

Esta respuesta proporciona un camino hacia una solución elegante:https://stackoverflow.com/a/1655389/642372

  1. readun heredoc en una variable de shell.
  2. Pase esa variable como argumento posicional a sed.

Muestra:

#!/usr/bin/env bash

read -rd '' SED_SCRIPT <<EOD      
# Your sed script goes here.
s/a/b/
EOD

exec sed "$SED_SCRIPT" "$@"
1
27.01.2020, 19:39

Мне нравится решение Уокера, но его можно улучшить (, поместив его в отдельный ответ, потому что комментарии не принимают предварительно отформатированный текст ). Это может работать не во всех версиях Linux или Bash, но в Ubuntu 17.10 вы можете сократить это до следующего:

#!/usr/bin/env bash
read SED_SCRIPT <<EOD
s/a/b/
EOD
sed "$SED_SCRIPT" "$@"

Вы можете удалить evalи упростить команду read, но вы должны избавиться от комментариев внутри heredoc.

Кроме того, для всего, что вы когда-либо хотели знать о sed, но боялись спросить, есть очень полезный туториал по адресуhttp://www.grymoire.com/unix/sed.html. Это предлагает еще лучшее решение за счет потери /usr/bin/envи жесткого -кодирования пути к sed :

.
#!/bin/sed -f
s/a/b/
s/c/d/

Это имеет дополнительное преимущество, заключающееся в поддержке более одной s///замены.

1
27.01.2020, 19:39

Начиная с GNU coreutils v8.30 , вы можете сделать:

#!/usr/bin/env -S sed -f

Эта функция была добавлена ​​в недавней (2018 -04 -20)фиксации в env.cв Пакет GNU coreutils, который добавил опцию -Sили --split-string.

Из справочной страницы env:

OPTIONS
-S/--split-string usage in scripts
    The  -S  option allows specifing multiple parameters in a script.
    Running a script named 1.pl containing the following first line:

            #!/usr/bin/env -S perl -w -T

    Will execute perl -w -T 1.pl.

    Without the '-S' parameter the script will likely fail with:

            /usr/bin/env: 'perl -w -T': No such file or directory

    See the full documentation for more details.

Дополнительные примеры доступны в руководстве GNU coreutils .

Если вы также используете опцию -vдля подробного вывода, вы можете увидеть, как именно envразбивает строку аргументов:

Вmy_sed_script.sed:

#!/usr/bin/env -vS sed -f
s/a/b/

Исполнение:

$./my_sed_script.sed
split -S:  ‘sed -f’
 into:    ‘sed’
     &    ‘-f’
executing: sed
   arg[0]= ‘sed’
   arg[1]= ‘-f’
   arg[2]= ‘./my_sed_script.sed’

Примечание.:Это относится только к шебангам, которые используют /usr/bin/env, т.к. --split-stringявляется особенностью GNU env.

9
27.01.2020, 19:39

Теги

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