Я использую Python -c
для выполнения однострочного цикла, то есть:
$ python -c "for r in range(10): print 'rob'"
Это отлично работает. Однако, если я импортирую модуль перед циклом for, я получаю синтаксическую ошибку:
$ python -c "import sys; for r in range(10): print 'rob'"
File "<string>", line 1
import sys; for r in range(10): print 'rob'
^
SyntaxError: invalid syntax
Есть идеи, как это можно исправить?
Для меня важно, чтобы это было в одной строке, чтобы я мог включить его в Makefile.
python
shell
command-line
heredoc
Мартино
источник
источник
Ответы:
ты мог бы сделать
или без труб:
или
или @ ответ SilentGhost / @ ответ Crast
источник
python -c "exec(\"import sys\nfor r in range(10): print('rob')\")"
этот стиль также может использоваться в make-файлах (и на самом деле он используется довольно часто).
или
в последнем случае также удаляются начальные символы табуляции (и может быть достигнут некоторый структурированный обзор)
вместо EOF может стоять любое маркерное слово, не появляющееся в документе здесь в начале строки (см. также здесь документы на странице руководства bash или здесь ).
источник
<<EOF
. Обратите внимание, однако, что лучше заключить в кавычки - например,<<'EOF'
- чтобы защитить содержимое документа здесь от расширений внешней оболочки .Проблема на самом деле не в операторе import, а в том, что что-то находится перед циклом for. Или, более конкретно, все, что появляется перед встроенным блоком.
Например, все это работает:
Если бы импорт, являющийся оператором, был проблемой, это бы сработало, но это не так:
Для вашего самого простого примера вы можете переписать его так:
Однако лямбда-выражения могут выполнять только выражения, а не операторы или множественные операторы, поэтому вы все равно не сможете делать то, что хотите. Однако между выражениями генератора, списком, лямбдами, sys.stdout.write, встроенной «картой» и некоторой творческой интерполяцией строк вы можете сделать несколько мощных однострочных.
Вопрос в том, как далеко вы хотите пойти, и в какой момент не лучше написать небольшой
.py
файл, который вместо этого выполняет ваш make-файл?источник
- Чтобы этот ответ работал и с Python 3.x ,
print
вызывается как функция : в 3.x работает толькоprint('foo')
, тогда как 2.x также принимаетprint 'foo'
.- Для кроссплатформенной перспективы, включающей Windows , смотрите полезный ответ kxr. .
В
bash
,ksh
илиzsh
:Используйте ANSI C- заключенную в кавычки строку (
$'...'
), которая позволяет использовать\n
для представления новых строк, которые расширяются до фактических новых строк перед передачей строкиpython
:Обратите внимание
\n
на операторы междуimport
иfor
для создания переноса строки.Чтобы передать значения переменных оболочки в такую команду, наиболее безопасно использовать аргументы и обращаться к ним через
sys.argv
скрипт Python:Ниже приведено обсуждение плюсов и минусов использования командной строки (escape-предварительная обработка) с двойными кавычками со встроенными ссылками на переменные оболочки.
Для безопасной работы со
$'...'
строками:\
экземпляры в вашем исходном коде.\<char>
последовательности - такие , как\n
в данном случае, но и обычные подозреваемые , такие как\t
,\r
,\b
- расширены путем$'...'
(смman printf
для поддерживаемых побегов)'
экземпляры как\'
.Если вы должны оставаться POSIX-совместимым :
Используйте
printf
с подстановкой команды :Чтобы безопасно работать с этим типом строки:
\
экземпляры в вашем исходном коде.\<char>
последовательности - такие , как\n
в данном случае, но и обычные подозреваемые , такие как\t
,\r
,\b
- расширены путемprintf
(смman printf
для поддерживаемых управляющих последовательностей).Проходят в одинарных кавычках строку
printf %b
и избежать внедренные одиночные кавычки , как'\''
(СИК).Использование одинарных кавычек защищает содержимое строки от интерпретации оболочкой .
Тем не менее, для коротких скриптов Python (как в данном случае) вы можете использовать строку в двойных кавычках для включения значений переменных оболочки в ваши скрипты - при условии, что вам известны связанные с этим подводные камни (см. Следующий пункт); например, оболочка расширяется
$HOME
до домашнего каталога текущего пользователя. в следующей команде:python -c "$(printf %b "import sys\nfor r in range(10): print('rob is $HOME')")"
Однако обычно предпочтительный подход заключается в передаче значений из оболочки через аргументы и доступ к ним через
sys.argv
Python; эквивалент вышеупомянутой команды:python -c "$(printf %b 'import sys\nfor r in range(10): print("rob is " + sys.argv[1])')" "$HOME"
Хотя использование строки в двойных кавычках более удобно - она позволяет использовать встроенные одинарные кавычки, неэкранированные и встроенные двойные кавычки, поскольку
\"
- это также делает строку подлежащей интерпретации оболочкой , что может быть или не быть намерением;$
и`
символы в вашем исходном коде, которые не предназначены для оболочки, могут вызвать синтаксическую ошибку или неожиданно изменить строку.\
обработка оболочки в строках в двойных кавычках; например, чтобы заставить Python производить буквальный выводro\b
, вы должны перейтиro\\b
к нему; с'...'
строкой оболочки и сдвоенными\
случаями, мы получаем:python -c "$(printf %b 'import sys\nprint("ro\\\\bs")')" # ok: 'ro\bs'
С другой стороны, это вовсе не работать как задумано с
"..."
строкой оболочки:python -c "$(printf %b "import sys\nprint('ro\\\\bs')")" # !! INCORRECT: 'rs'
Оболочка интерпретирует как
"\b"
и"\\b"
как буквальные\b
, требующую головокружительное количество дополнительных\
экземпляров для достижения желаемого эффекта:python -c "$(printf %b "import sys\nprint('ro\\\\\\\\bs')")"
Для того, чтобы пройти через код
stdin
, а не-c
:Примечание: Я сосредоточен на отдельных -LINE решений здесь; В ответе xorho показано, как использовать многострочный документ здесь - однако обязательно указывайте разделитель; например,
<<'EOF'
если вы явно не хотите, чтобы оболочка расширила строку заранее (что сопровождается оговорками, указанными выше).В
bash
,ksh
илиzsh
:Объединить ANSI C- кавычки строку (
$'...'
) с здесь-строкой (<<<...
):-
говоритpython
явно читать из стандартного ввода (что он делает по умолчанию).-
в этом случае является необязательным, но если вы также хотите передать аргументы в сценарии, вам нужно это для устранения неоднозначности аргумента из имени файла сценария:Если вы должны оставаться POSIX-совместимым :
использование
printf
как указано выше, но с конвейером, чтобы передать свой вывод через stdin:С аргументом:
источник
Ваша проблема вызвана тем фактом, что операторы Python, разделенные символами
;
, могут быть только «небольшими операторами», которые являются однострочными. Из файла грамматики в документации по Python :Составные операторы не могут быть включены в одну строку с другими операторами через точку с запятой - так что делать это с
-c
флагом становится очень неудобно.Когда я демонстрирую Python в среде оболочки bash, я считаю очень полезным включать составные операторы. Единственный простой способ сделать это надежно - с помощью heredocs (posix shell).
Heredocs
Используйте Heredoc (создано
<<
) и Python, вариант интерфейса командной строки ,-
:Добавление
-
после<<
(the<<-
) позволяет использовать вкладки для отступа (Stackoverflow преобразует вкладки в пробелы, поэтому я выделил 8 пробелов, чтобы подчеркнуть это). Ведущие вкладки будут удалены.Вы можете сделать это без вкладок просто
<<
:Помещение кавычек
EOF
предотвращает расширение параметров и арифметику . Это делает heredoc более устойчивым.Bash многострочные строки
Если вы используете двойные кавычки, вы получите расширение оболочки:
Чтобы избежать расширения оболочки, используйте одинарные кавычки:
Обратите внимание, что нам нужно поменять символы кавычек на литералы в Python - мы в основном не можем использовать символы кавычек, интерпретируемые BASH. Мы можем чередовать их, как и в Python, но это уже выглядит довольно странно, поэтому я не рекомендую это:
Критика принятого ответа (и других)
Это не очень читабельно:
Не очень читабельно и дополнительно сложно отладить в случае ошибки:
Возможно, немного более читабельным, но все еще довольно некрасиво:
Вы будете иметь плохое время, если у вас есть
"
в вашем питоне:Не злоупотребляйте
map
и не перечисляйте понимания, чтобы получить циклы:Это все грустно и плохо. Не делай их.
источник
bash
,ksh
илиzsh
) является разумным решением:python -c $'import sys\nfor r in range(10): print(\'rob\')'
(вам придется беспокоиться только об экранировании одинарных кавычек (чего можно избежать, используя двойные кавычки) и обратные косые).просто используйте return и введите его в следующую строку:
источник
python $(srcdir)/myscript.py
для великого правосудия.$ python2.6 -c "import sys; [sys.stdout.write('rob\n') for r in range(10)]"
Работает отлично. Используйте «[]», чтобы встроить цикл for.
источник
Проблема не в
import
утверждении. Проблема в том, что операторы потока управления не работают встроенными в команду python. Замените этоimport
утверждение любым другим утверждением, и вы увидите ту же проблему.Подумайте об этом: питон не может встроить все. Он использует отступ для группировки потока управления.
источник
Если ваша система соответствует стандарту Posix.2, она должна предоставить
printf
утилиту:источник
printf %b '...' | python
для повышения надежности, потому что это препятствуетprintf
интерпретации последовательностей, таких как%d
(спецификаторы формата) во входной строке. Кроме того, если вы явно не хотите применять расширения оболочки к командной строке Python заранее (что может привести к путанице), лучше использовать'
(одинарные кавычки) для внешнего цитирования, чтобы избежать как расширений, так и обработки обратной реакции, применяемой оболочкой. в двойных кавычках.single/double quotes
иbackslash
везде:Намного лучше:
источник
(ответил 23 ноября 2010 года в 19:48) Я на самом деле не большой Pythoner - но однажды я нашел этот синтаксис, забыл, откуда, поэтому я решил документировать его:
если вы используете
sys.stdout.write
вместоprint
( разница заключается в том, чтоsys.stdout.write
аргументы принимаются как функция, в скобках - тогда какprint
нет ), то для однострочного вы можете избежать инвертирования порядка команды иfor
удаления точки с запятой, и заключив команду в квадратные скобки, то есть:Понятия не имею, как этот синтаксис будет называться в Python :)
Надеюсь это поможет,
Ура!
(РЕДАКТИРОВАТЬ Вт 9 апреля 20:57:30 2013) Ну, я думаю, я наконец нашел, что эти квадратные скобки в однострочниках; они являются «списочным пониманием» (по-видимому); сначала отметьте это в Python 2.7:
Таким образом, команда в круглых скобках / скобках рассматривается как «объект генератора»; если мы «переберем» его, вызвав
next()
- тогда будет выполнена команда внутри скобки (обратите внимание на «abc» в выходных данных):Если мы теперь используем квадратные скобки - обратите внимание, что нам не нужно вызывать
next()
команду для ее выполнения, она выполняется сразу после назначения; Однако, спустя осмотр показывает , чтоa
этоNone
:Это не оставляет много информации для поиска в квадратных скобках - но я наткнулся на эту страницу, которая, я думаю, объясняет:
Python Tips And Tricks - Первое издание - Уроки Python | Dream.In.Code :
И действительно, это список - это просто его первый элемент, который становится ничем, как только он выполняется:
Понимание списка иначе документировано в 5. Структуры данных: 5.1.4. Постижения списков - документация Python v2.7.4 как « Постижения списков обеспечивают краткий способ создания списков»; по-видимому, именно здесь ограниченная «выполнимость» списков вступает в игру в одну строку.
Что ж, надеюсь, я не так уж и плох
EDIT2: и вот однострочная командная строка с двумя не вложенными циклами for; оба заключены в квадратные скобки «понимание списка»:
Обратите внимание, что второй «список»
b
теперь имеет два элемента, поскольку цикл for явно запускается дважды; Однако результатsys.stdout.write()
в обоих случаях был (по-видимому)None
.источник
Этот вариант наиболее переносим для размещения многострочных сценариев в командной строке в Windows и * nix, py2 / 3, без конвейеров:
(Ни один из других примеров, увиденных здесь до сих пор, не сделал так)
Аккуратно на Windows это:
Neat на bash / * nix это:
Эта функция превращает любой многострочный скрипт в переносимую команду-однострочник:
Использование:
Вход был:
источник
--%
перед аргументом командной строки.print "path is %%PATH%%"
соотв.print "path is $PATH"
обычно это вариант, который требуется в скрипте или командной строке - если не избежать обычных вещей для платформы. То же самое с другими языками. (Сам синтаксис Python не$foo
в вашем коде Python? Если вы избежите этого как\$foo
в пользу POSIX-подобных оболочек,cmd.exe
все равно увидите дополнительное\
. Это может быть редко, но это стоит знать.Этот скрипт предоставляет Perl-подобный интерфейс командной строки:
Pyliner - скрипт для запуска произвольного кода Python из командной строки (рецепт Python)
источник
Когда мне нужно было сделать это, я использую
Обратите внимание на тройную обратную косую черту для новой строки в операторе sys.stdout.write.
источник
echo -e
, что является нестандартным и требуетbash
,ksh
илиzsh
вы также можете использовать$'...'
строку напрямую, что также упрощает экранирование:python -c $'import sys\nsys.stdout.write("Hello World!\\n")'
Я хотел решение со следующими свойствами:
Оба требования не были предоставлены в других ответах, так что вот как читать stdin при выполнении всего в командной строке:
источник
есть еще одна опция, sys.stdout.write возвращает None, что делает список пустым
источник
Если вы не хотите трогать stdin и имитировать, как если бы вы передали «python cmdfile.py», вы можете сделать следующее из оболочки bash:
Как видите, он позволяет использовать stdin для чтения входных данных. Внутренне оболочка создает временный файл для содержимого входной команды.
источник
-c "$(...)"
делает то же самое и является POSIX-совместимым); дать<(...)
конструкции имя: подстановка процесса ; это также работает вksh
иzsh
.