Использование подстановочного знака в команде zsh fc

En Linux, el shebang no es muy flexible; de acuerdo con las respuestas múltiples(de Stephen Kitt y de Jörg W Mittag ), no hay una forma designada de pasar múltiples argumentos en una línea shebang.

No estoy seguro de si será útil para alguien, pero he escrito un breve script para implementar la función que falta. Véasehttps://gist.github.com/loxaxs/7cbe84aed1c38cf18f70d8427bed1efa.

También es posible escribir soluciones integradas. A continuación, presento cuatro soluciones temporales -agnósticas aplicadas al mismo script de prueba y el resultado que cada una imprime. Supongo que el script es ejecutable y está en /tmp/shebang.


Envolviendo su script en un bash heredoc dentro de la sustitución del proceso

Hasta donde yo sé, esta es la forma más confiable -agnóstica de hacerlo. Permite pasar argumentos y conserva stdin.El inconveniente es que el intérprete no conoce la ubicación (real )del archivo que lee.

#!/bin/bash
exec python3 -O <(cat << 'EOWRAPPER'
print("PYTHON_SCRIPT_BEGINNING")

from sys import argv
try:
    print("input() 0 ::", input())
    print("input() 1 ::", input())
except EOFError:
    print("input() caused EOFError")
print("argv[0]   ::", argv[0])
print("argv[1:]  ::", argv[1:])
print("__debug__ ::", __debug__)
# The -O option changes __debug__ to False

print("PYTHON_SCRIPT_END")
EOWRAPPER
) "$@"

Llamando echo -e 'aa\nbb' | /tmp/shebang 'arg1' 'arg2 contains spaces' 'arg3\ uses\ \\escapes\\'imprime:

PYTHON_SCRIPT_BEGINNING
input() 0 :: aa
input() 1 :: bb
argv[0]   :: /dev/fd/62
argv[1:]  :: ['arg1', 'arg2 contains spaces', 'arg3\\ uses\\ \\\\escapes\\\\']
__debug__ :: False
PYTHON_SCRIPT_END

Tenga en cuenta que la sustitución de procesos produce un archivo especial. Esto puede no ser adecuado para todos los ejecutables. Por ejemplo, #!/usr/bin/lessse queja:/dev/fd/63 is not a regular file (use -f to see it)

No sé si es posible tener heredoc dentro de la sustitución del proceso en el guión.


Envolviendo su script en un heredoc simple

Más corto y más simple, pero no podrá acceder a stdindesde su secuencia de comandos y requiere que el intérprete pueda leer y ejecutar una secuencia de comandos desde stdin.

#!/bin/sh
exec python3 - "$@" << 'EOWRAPPER'
print("PYTHON_SCRIPT_BEGINNING")

from sys import argv

try:
    print("input() 0 ::", input())
    print("input() 1 ::", input())
except EOFError:
    print("input() caused EOFError")
print("argv[0]   ::", argv[0])
print("argv[1:]  ::", argv[1:])
print("__debug__ ::", __debug__)
# The -O option changes __debug__ to False

print("PYTHON_SCRIPT_END")
EOWRAPPER

Llamando echo -e 'aa\nbb' | /tmp/shebang 'arg1' 'arg2 contains spaces' 'arg3\ uses\ \\escapes\\'imprime:

PYTHON_SCRIPT_BEGINNING
input() caused EOFError
argv[0]   :: -
argv[1:]  :: ['arg1', 'arg2 contains spaces', 'arg3\\ uses\\ \\\\escapes\\\\']
__debug__ :: True
PYTHON_SCRIPT_END

Usar llamada awk system()pero sin argumentos

Pasa correctamente el nombre del archivo ejecutado, pero su script no recibirá los argumentos que le da. Tenga en cuenta que awk es el único idioma que conozco cuyo intérprete está instalado en Linux de forma predeterminada y lee sus instrucciones desde la línea de comandos de forma predeterminada.

#!/usr/bin/gawk BEGIN {system("python3 -O " ARGV[1])}
print("PYTHON_SCRIPT_BEGINNING")

from sys import argv

print("input() 0 ::", input())
print("input() 1 ::", input())
print("argv[0]   ::", argv[0])
print("argv[1:]  ::", argv[1:])
print("__debug__ ::", __debug__)
# The -O option changes __debug__ to False

print("PYTHON_SCRIPT_END")

Llamando echo -e 'aa\nbb' | /tmp/shebang 'arg1' 'arg2 contains spaces' 'arg3\ uses\ \\escapes\\'imprime:

PYTHON_SCRIPT_BEGINNING
input() 0 :: aa
input() 1 :: bb
argv[0]   :: /tmp/shebang
argv[1:]  :: []
__debug__ :: False
PYTHON_SCRIPT_END

Use la llamada awk 4.1+ system(), siempre que sus argumentos no contengan espacios

Bien, pero solo si está seguro de que su secuencia de comandos no se llamará con argumentos que contengan espacios. Como puede ver, sus argumentos que contienen espacios se dividirán, a menos que se escapen los espacios.

#!/usr/bin/gawk @include "join"; BEGIN {system("python3 -O " join(ARGV, 1, ARGC, " "))}
print("PYTHON_SCRIPT_BEGINNING")

from sys import argv

print("input() 0 ::", input())
print("input() 1 ::", input())
print("argv[0]   ::", argv[0])
print("argv[1:]  ::", argv[1:])
print("__debug__ ::", __debug__)
# The -O option changes __debug__ to False

print("PYTHON_SCRIPT_END")

Llamando echo -e 'aa\nbb' | /tmp/shebang 'arg1' 'arg2 contains spaces' 'arg3\ uses\ \\escapes\\'imprime:

PYTHON_SCRIPT_BEGINNING
input() 0 :: aa
input() 1 :: bb
argv[0]   :: /tmp/shebang
argv[1:]  :: ['arg1', 'arg2', 'contains', 'spaces', 'arg3 uses \\escapes\\']
__debug__ :: False
PYTHON_SCRIPT_END

Para las versiones de awk anteriores a la 4.1, tendrá que usar la concatenación de cadenas dentro de un bucle for, consulte la función de ejemplohttps://www.gnu.org/software/gawk/manual/html_node/Join-Function.html.

1
20.06.2019, 20:04
2 ответа

Нет, нет хорошего способа «заставить этот псевдоним правильно использовать подстановочный знак», потому что «правильно» означает разные вещи в разных случаях. Например, если в командной строке была подстановка команд, вы имели в виду запустить эту другую команду от имени пользователя root или нет? Тип автоматизации, который вам нужен, очень удобен для быстрого выполнения неправильных действий. Это все равно, что закрывать глаза, когда переходишь улицу, потому что смотреть на машины слишком утомительно.

Мой совет: наберите ВверхHomesudoПробел и найдите время, чтобы заново -прочитать команду, чтобы убедиться, что то, что вы делаете, это то, что вы хотели сделать.

Тем не менее, если вы любите риск, конечно, вы можете заставить свой компьютер сделать что-нибудь . Вот два решения, которые делают разные вещи.

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

please () {
  setopt local_options err_exit
  local args
  eval "args=($history[$((HISTCMD-1))])"
  print -lr Running sudo "$args[@]"
  sleep 2
  sudo "$args[@]"
}

Следующая команда предполагает, что предыдущая команда не изменяла среду оболочки и не полагалась ни на какие переменные среды. Он запускает всю командную строку от имени пользователя root, включая расширения подстановочных знаков, подстановки команд и т. д.

please () {
  sudo zsh -c "$history[$HISTCMD]"
}
2
27.01.2020, 23:30

Похоже, единственное решение:

alias please='eval sudo $(fc -nl -1)'
0
27.01.2020, 23:30

Теги

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