Гібридний код у скриптах оболонки. Обмін змінними


10

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

#!/bin/bash
some_text="Hello world"
echo $some_text

cat <<EOF | python -
import sys;
for r in range(3):
  print r
  for a in range(2):
    print "hello"
EOF

відбитки:

0 
hello
hello
1
hello
hello
2
hello
hello

Однак мені важко ділитися змінними між сценарієм оболонки та фрагментом Python.

  1. Як я можу зібрати висновок підпіска python у скрипті bash? (наприклад, у такій змінній, як $output).

  2. Як я можу передати змінну bash (наприклад $some_text) до сценарію Python?


1
Ви можете зробити python - <<EOFзамість цього.

jftr imo це поганий стиль, і вам слід спробувати цього уникнути
Ульріх Дангел

1
Чому тег / zsh?
Стефан Шазелас

Відповіді:


12

Отримання змінної на Python

Оскільки (коли EOFмаркер не котирується) підміна змінної відбувається до того, як текст буде переданий з гередока на pythonстандартний вхід, ви можете кинути змінну право в сценарій.

python - <<EOF
some_text = "$some_text"
EOF

Якби some_textбув test, пітон побачив би some_text = "test". Зауважте, що це може розглядатися як вразливість кодового введення. Якщо some_textбув "; import os; os.system("evil-command"); x = ", наприклад, пітон б бачити:

some_text = ""; import os; os.system("evil-command"); x = ""

і виконуй цю злу команду.

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

export some_text

і використовувати його os.environдля отримання.

some_text = os.environ['some_text']

Це набагато безпечніший / безпечніший підхід.


Отримання виводу з Python

Ви можете використовувати заміну команд для збору результатів сценарію.

output=$(
python - <<EOF
import sys;
for r in range(3):
  print r
  for a in range(2):
    print "hello"
EOF
)

(зауважте, що всі символи нового рядка видалено)


Це виглядає чудово. Коли ви сказали "You could also pass the variable to the script as an argument", як би ви це зробили, враховуючи, що сценарій Python вбудований в сценарій оболонки?
Амеліо Васкес-Рейна

Вибачте, я забув про це на секунду. Я видалив цей розчин і додав кращого рішення.

Будьте уважні, як ви називаєте маркер гередока. Коли це не буде котируватися, як у вашому прикладі, відбудеться розширення оболонки в рядку heredoc. Наприклад, якщо ваш код python складався з справедливих print '$SHELL', результатом буде /bin/bashабо що б не було вашої оболонки. Якщо змінити перший рядок на python - <<'END', то буде вихід $SHELL. Якщо ви копіюєте та вставляєте наявний код для вбудовування в bash-скрипт, ви майже напевно не хочете, щоб заміна оболонки - ви хочете, щоб код запускався так само, як це робиться, коли він не вбудований у скрипт bash, правда?
Кріс Джонсон

8

Проблема вашого підходу полягає в тому, що вбудований сценарій python більше не має доступу до оригінального stdin (оскільки його stdin - це ... сам).

Якщо це питання, ви можете написати:

python -c '
import sys;
for r in range(3):
  print r
  for a in range(2):
    print "hello"
'

Або якщо сценарій python може містити одинарні лапки:

python -c "$(cat << 'EOF'
import sys;
for r in range(3):
  print r
  for a in range(2):
    print "hello"
EOF
)"

Або:

python <(cat << 'EOF'
import sys;
for r in range(3):
  print r
  for a in range(2):
    print "hello"
EOF
)

6

Використовуйте тире як ім'я файлу:

ruby - a b <<'END'
puts ARGV.join(",")
END

python - a b <<'END'
import sys
print ",".join(sys.argv[1:])
END

Я не знаю, чи sys.argv[1:]це правильний спосіб зробити це в Python. Для -e / -c ви можете вказати кінець аргументів за допомогою:

set -- -a -b -c
ruby -e 'puts ARGV.join(",")' -- "$@"
python -c 'import sys; print ",".join(sys.argv[2:])' -- "$@"

Захоплення виводу та переадресація STDERR:

x=$(ruby <<'END' 2> /dev/null
puts "a"
abort "b"
END
)

2

1) Ви можете записати змінні призначення до файлу в python, а потім джерело цього у вашому скрипті bash.

2) Оскільки ваше слово (EOF) не цитується, всі рядки документа тут піддаються розширенню параметрів. Ви можете використовувати це для передачі матеріалів до сценарію python.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.