Wykonywanie poleceń Pythona w jednym wierszu poleceń
Używam Pythona z -c
do wykonania pętli jednowierszowej, tzn.:
$ python -c "for r in range(10): print 'rob'"
To działa dobrze. Jeśli jednak zaimportuję moduł przed pętlą for, pojawia się błąd składni:
$ 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
Wiesz, jak to naprawić?
Ważne jest dla mnie, aby mieć to jako jednolinijkowy, abym mógł to umieścić w pliku Makefile.
17 answers
You could do
echo -e "import sys\nfor r in range(10): print 'rob'" | python
Lub rury w / out:
python -c "exec(\"import sys\\nfor r in range(10): print 'rob'\")"
Lub
(echo "import sys" ; echo "for r in range(10): print 'rob'") | python
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:44
Ten styl może być również używany w plikach Makefile (i w rzeczywistości jest używany dość często).
python - <<EOF
import sys
for r in range(3): print 'rob'
EOF
Lub
python - <<-EOF
import sys
for r in range(3): print 'rob'
EOF
W drugim przypadku znaki tabulacji są również usuwane (i można uzyskać pewien ustrukturyzowany outlook)
Zamiast EOF może zawierać dowolne słowo znacznikowe, które nie pojawia się w dokumencie here na początku linii (patrz również tutaj dokumenty na stronie podręcznika bash lub tutaj ).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-25 01:01:15
Problem nie dotyczy instrukcji import, tylko tego, co znajduje się przed pętlą for. A dokładniej, wszystko, co pojawia się przed wbudowanym blokiem.
Na przykład te wszystkie działają:
python -c "import sys; print 'rob'"
python -c "import sys; sys.stdout.write('rob\n')"
Jeśli import będący oświadczeniem byłby problemem, to działałoby, ale tak nie jest:
python -c "__import__('sys'); for r in range(10): print 'rob'"
Dla twojego bardzo podstawowego przykładu, możesz napisać go od nowa Tak:
python -c "import sys; map(lambda x: sys.stdout.write('rob%d\n' % x), range(10))"
Jednak lambda może wykonywać tylko wyrażenia, a nie instrukcje lub wiele instrukcji, więc możesz nadal nie możesz robić tego, co chcesz. Natomiast pomiędzy wyrażeniami generatora, list comprehension, lambda, sys.stdout.napisz, wbudowana" mapa " i kilka kreatywnych interpolacji ciągów, możesz zrobić kilka potężnych jednolinijkowych.
Pytanie brzmi, jak daleko chcesz się posunąć i w którym momencie nie lepiej jest napisać mały plik .py
, który zamiast tego wykonuje Twój plik makefile?
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-11 17:39:30
- Aby ta odpowiedź działała z Pythonem 3.x również print
jest wywoływana jako funkcja : W 3.x, tylko print('foo')
działa, natomiast 2.x akceptuje również print 'foo'
.
-Dla perspektywy wieloplatformowej, która obejmuje Windows, zobacz pomocna odpowiedź kxr.
W bash
, ksh
, lub zsh
:
Użyj ANSI C-cytowany ciąg znaków ($'...'
), co pozwala używać \n
do reprezentowania nowych linii są one rozszerzane do nowych linii przed przekazaniem do python
:
python -c $'import sys\nfor r in range(10): print("rob")'
Zwróć uwagę na \n
pomiędzy import
i for
, aby spowodować przerwanie linii.
Aby przekazać wartości zmiennej powłoki do takiego polecenia, najbezpieczniej jest użyć argumentów i uzyskać do nich dostęp poprzez sys.argv
wewnątrz skryptu Pythona:
name='rob' # value to pass to the Python script
python -c $'import sys\nfor r in range(10): print(sys.argv[1])' "$name"
poniżej omówienie zalet i wad użycia (Sekwencja escape-preprocessed) Double-quoted string with embedded Shell-variable references.
Aby bezpiecznie pracować z$'...'
ciągami:
-
Double
\
instancje w Twoim oryginalnym kodzie źródłowym.-
\<char>
sekwencje - takie jak\n
w tym przypadku, ale także zwykłe podejrzane, takie jak\t
,\r
,\b
- są rozszerzane o$'...'
(zobacz {[28] } dla obsługiwanych Escape)
-
- Escape
'
instancje jako\'
.
Jeśli musisz pozostać zgodny z POSIX :
Użyj printf
Z zastąpienie polecenia :
python -c "$(printf %b 'import sys\nfor r in range(10): print("rob")')"
Aby bezpiecznie pracować z tego typu ciągiem:
-
Double
\
instancje w Twoim oryginalnym kodzie źródłowym.-
\<char>
sekwencje - takie jak\n
w tym przypadku, ale także zwykłe podejrzane, takie jak\t
,\r
,\b
- są rozszerzone oprintf
(zobaczman printf
dla wspieranego escape sekwencji).
-
-
Przekaż pojedynczy cytat łańcuch do
printf %b
i unikaj osadzonych pojedynczych cudzysłowów jako'\''
(sic).-
Użycie pojedynczych cudzysłowów chroni zawartość łańcucha przed interpretacją przez powłokę .
-
To powiedziawszy, dla krótkich skryptów Pythona (jak w tym przypadku) możesz użyć podwójnego cytowanego ciągu, aby włączyć shell wartości zmiennych do swoich skryptów - tak długo, jak na przykład powłoka rozszerza
$HOME
do katalogu domowego bieżącego użytkownika. w następującym poleceniu:python -c "$(printf %b "import sys\nfor r in range(10): print('rob is $HOME')")"
-
Jednak ogólnie preferowanym podejściem jest przekazywanie wartości z powłoki przez argumenty , A dostęp do nich przez
sys.argv
w Pythonie; odpowiednikiem powyższego polecenia jest:python -c "$(printf %b 'import sys\nfor r in range(10): print("rob is " + sys.argv[1])')" "$HOME"
-
-
Podczas korzystania z double-quoted string jest bardziej wygodny - pozwala na używanie osadzonych pojedynczych cudzysłowów bez znaków i osadzonych podwójnych cudzysłowów jako
\"
- sprawia również, że łańcuch jest interpretowany przez powłokę , co może, ale nie musi być intencją;$
i`
w kodzie źródłowym, które nie są przeznaczone dla powłoki, może spowodować błąd składni lub nieoczekiwanie zmienić łańcuch.- dodatkowo, powłoki własne
\
przetwarzanie w na przykład, aby uzyskać Python , aby wytworzyć literalne wyjściero\b
, musisz przekazaćro\\b
do niego; z'...'
łańcuch powłoki i dwukrotnie\
instancje, otrzymujemy:python -c "$(printf %b 'import sys\nprint("ro\\\\bs")')" # ok: 'ro\bs'
W przeciwieństwie do tego, to Nie działa zgodnie z przeznaczeniem z"..."
łańcuchem powłoki:python -c "$(printf %b "import sys\nprint('ro\\\\bs')")" # !! INCORRECT: 'rs'
Powłoka interpretuje zarówno"\b"
i"\\b"
jako dosłowne\b
, wymagające zawrotnej liczby dodatkowych\
instancji, aby osiągnąć pożądany efekt:python -c "$(printf %b "import sys\nprint('ro\\\\\\\\bs')")"
- dodatkowo, powłoki własne
-
Do prześlij Kod przez stdin
zamiast -c
:
Uwaga: skupiam się na single-line solutions here; odpowiedź xorho pokazuje, jak używać wielowierszowego here-document - pamiętaj, aby cytować ogranicznik, jednak; na przykład, <<'EOF'
, chyba że wyraźnie chcesz, aby powłoka rozszerzyła łańcuch z przodu (co pochodzi z zastrzeżeniami zauważonymi powyżej).
W bash
, ksh
, lub zsh
:
Połącz ANSI C-cytowany ciąg znaków ($'...'
) z tutaj-ciąg (<<<...
):
python - <<<$'import sys\nfor r in range(10): print("rob")'
-
mówi python
jawnie do odczytu ze standardowego wejścia (co robi domyślnie).
-
jest opcjonalne w tym przypadku, ale jeśli chcesz również przekazać argumenty do skryptów, musisz rozdzielić argument z nazwy pliku skryptu:
python - 'rob' <<<$'import sys\nfor r in range(10): print(sys.argv[1])'
Jeśli musi pozostać zgodne z POSIX :
Użyj printf
jak wyżej, ale z rurociągiem , aby przekazać swoje wyjście przez stdin:
printf %b 'import sys\nfor r in range(10): print("rob")' | python
Z argumentem:
printf %b 'import sys\nfor r in range(10): print(sys.argv[1])' | python - 'rob'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:22
Po prostu użyj return i wpisz go w następnej linii:
user@host:~$ python -c "import sys
> for r in range(10): print 'rob'"
rob
rob
...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-11 17:14:19
Wiesz, jak to naprawić?
Twój problem jest spowodowany faktem, że wyrażenia Pythona, oddzielone przez ;
, mogą być tylko "małymi wyrażeniami", które są jednowierszowymi. Z pliku gramatyki w Python docs :
stmt: simple_stmt | compound_stmt simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | nonlocal_stmt | assert_stmt)
Wyrażenia złożone nie mogą być dołączane do tej samej linii z innymi wyrażeniami za pomocą średników - więc robienie tego ze znacznikiem -c
staje się bardzo niewygodne.
Podczas demonstracji Python podczas gdy w środowisku powłoki bash, uważam, że bardzo przydatne jest dołączanie poleceń złożonych. Jedynym prostym sposobem na to jest heredocs.
Heredocs
Użyj heredoc (utworzonego za pomocą <<
) i opcji interfejsu linii poleceń Pythona , -
:
$ python - <<-"EOF"
import sys # 1 tab indent
for r in range(10): # 1 tab indent
print('rob') # 1 tab indent and 4 spaces
EOF
Dodanie -
po <<
(<<-
) pozwala na użycie tabulatorów do wcięcia (Stackoverflow konwertuje tabulatory na spacje, więc wciąłem 8 spacji, aby to podkreślić). Na tabulatory wiodące zostaną usunięte.
Możesz to zrobić bez zakładek za pomocą tylko <<
:
$ python - << "EOF"
import sys
for r in range(10):
print('rob')
EOF
Umieszczenie cudzysłowów wokół EOF
zapobiega parametrowi i ekspansji arytmetycznej . To sprawia, że heredoc jest bardziej wytrzymały.
Krytyka zaakceptowanej odpowiedzi (i innych)
To nie jest zbyt czytelne:
echo -e "import sys\nfor r in range(10): print 'rob'" | python
Niezbyt czytelny, a dodatkowo trudny do debugowania w przypadku błąd:
python -c "exec(\"import sys\\nfor r in range(10): print 'rob'\")"
Może trochę bardziej czytelny, ale nadal dość brzydki:
(echo "import sys" ; echo "for r in range(10): print 'rob'") | python
Będziesz miał zły czas, jeśli masz "
' s w swoim Pythonie:
$ python -c "import sys > for r in range(10): print 'rob'"
Nie nadużywaj map
ani list składających, aby uzyskać pętle for:
To wszystko jest smutne i złe. Nie rób tego.python -c "import sys; map(lambda x: sys.stdout.write('rob%d\n' % x), range(10))"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-07 18:20:43
Problem nie dotyczy import
stwierdzenia. Problem polega na tym, że polecenia control flow nie działają inline w poleceniu Pythona. Zastąp import
instrukcję dowolną inną instrukcją, a zobaczysz ten sam problem.
Pomyśl o tym: python nie może wszystkiego wbudować. Wykorzystuje wcięcia do grupowania przepływu sterowania.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-11 17:19:27
Jeśli Twój system jest Posix.2012-01-23 14: 00: 00]}
$ printf "print 'zap'\nfor r in range(3): print 'rob'" | python
zap
rob
rob
rob
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-12 01:33:45
$ python2.6 -c "import sys; [sys.stdout.write('rob\n') for r in range(10)]"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-11 13:40:49
(odpowiedział 23 listopada '10 o 19: 48) Nie jestem naprawdę wielkim Pythonerem - ale znalazłem tę składnię raz, zapomniałem skąd, więc pomyślałem, że to udokumentuję: {]}
Jeśli używasz sys.stdout.write
zamiast print
(różnica polega na tym, że sys.stdout.write
przyjmuje argumenty jako funkcję, w nawiasie - podczas gdy print
Nie ), wtedy dla jednowierszowej można odwrócić kolejność polecenia i for
, usunąć średnik i zamknąć polecenie w nawiasach kwadratowych, tzn.:
python -c "import sys; [sys.stdout.write('rob\n') for r in range(10)]"
Nie mam pojęcia jak ta składnia będzie wywoływana w Pythonie:)
Mam nadzieję, że to pomoże,
Zdrówko!(EDIT WT Kwi 9 20:57:30 2013) Cóż, myślę, że w końcu odkryłem, o czym są te nawiasy kwadratowe w jednowierszowych; są to" składanie list " (najwyraźniej); najpierw zauważ to w Pythonie 2.7: {]}
$ STR=abc
$ echo $STR | python -c "import sys,re; a=(sys.stdout.write(line) for line in sys.stdin); print a"
<generator object <genexpr> at 0xb771461c>
Więc polecenie w nawiasach okrągłych jest postrzegane jako "obiekt generatora"; jeśli "iterujemy" przez niego wywołując next()
- następnie zostanie wykonana Komenda wewnątrz nawiasu (zwróć uwagę na " abc " na wyjściu):
$ echo $STR | python -c "import sys,re; a=(sys.stdout.write(line) for line in sys.stdin); a.next() ; print a"
abc
<generator object <genexpr> at 0xb777b734>
Jeśli teraz używamy nawiasów kwadratowych-zauważ, że nie musimy wywoływać next()
, aby polecenie Wykonało się natychmiast po przypisaniu; jednak późniejsza inspekcja ujawnia, że a
to None
:
$ echo $STR | python -c "import sys,re; a=[sys.stdout.write(line) for line in sys.stdin]; print a"
abc
[None]
To nie pozostawia wiele informacji do szukania, dla przypadku nawiasów kwadratowych - ale natknąłem się na tę stronę, która myślę, że wyjaśnia: {]}
Porady I Triki Pythona – Pierwsze Wydanie - Python Tutorials / Dream.In. Code:
W rzeczywistości jest to lista-po prostu jej pierwszy element staje się none, gdy tylko zostanie wykonany:]}Jeśli pamiętasz, standardowy format generatora jednowierszowego jest rodzajem pętli jednowierszowej " for " wewnątrz nawiasów. Spowoduje to powstanie "jednorazowego" obiektu iterowalnego, który jest obiektem, który można iterować tylko w jednym kierunku i którego nie można ponownie użyć po dotarciu do końca.
'rozumienie listy' wygląda prawie tak samo jak zwykły generator jednowierszowy, z tą różnicą, że zwykłe nawiasy - () - są zastępowane w nawiasach kwadratowych - []. Główną zaletą rozumienia jest to, że tworzy "listę", a nie "jednorazowy" obiekt iteracyjny, dzięki czemu można go przeglądać, dodawać elementy, sortować itp.
$ echo $STR | python -c "import sys,re; print [sys.stdout.write(line) for line in sys.stdin].__class__"
abc
<type 'list'>
$ echo $STR | python -c "import sys,re; print [sys.stdout.write(line) for line in sys.stdin][0]"
abc
None
Zestawienie List jest inaczej udokumentowane w 5. Struktury Danych: 5.1.4. Składanie List-Python v2.7.4 documentation as " lista składanie zapewnia zwięzły sposób tworzenia list"; prawdopodobnie w tym miejscu pojawia się ograniczona "wykonalność" list w jednolinijkach.
Cóż, mam nadzieję, że nie jestem zbytnio poza tym znamieniem ...EDIT2: a oto jednoliniowa linia poleceń z dwoma Nie zagnieżdżonymi pętlami for; obie zamknięte w kwadratowych nawiasach "rozumienie listy":
$ echo $STR | python -c "import sys,re; a=[sys.stdout.write(line) for line in sys.stdin]; b=[sys.stdout.write(str(x)) for x in range(2)] ; print a ; print b"
abc
01[None]
[None, None]
Zauważ, że druga " lista "b
ma teraz dwa elementy, ponieważ jej pętla for przebiegała wyraźnie dwukrotnie; jednak wynik sys.stdout.write()
w obu przypadkach był (najwyraźniej) None
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-09 19:32:39
Ten wariant jest najbardziej przenośny do umieszczania skryptów wielowierszowych w wierszu poleceń w systemach Windows i * Nix, py2/3, bez pipes:
python -c "exec(\"import sys \nfor r in range(10): print('rob') \")"
(żaden z innych przykładów tutaj do tej pory tak nie zrobił)
Schludny w Windows To:
python -c exec"""import sys \nfor r in range(10): print 'rob' """
python -c exec("""import sys \nfor r in range(10): print('rob') """)
Neat on bash / * nix is:
python -c $'import sys \nfor r in range(10): print("rob")'
Ta funkcja zamienia dowolny skrypt wielowierszowy w przenośny command-one-liner:
def py2cmdline(script):
exs = 'exec(%r)' % re.sub('\r\n|\r', '\n', script.rstrip())
print('python -c "%s"' % exs.replace('"', r'\"'))
Użycie:
>>> py2cmdline(getcliptext())
python -c "exec('print \'AA\tA\'\ntry:\n for i in 1, 2, 3:\n print i / 0\nexcept:\n print \"\"\"longer\nmessage\"\"\"')"
Wejście było:
print 'AA A'
try:
for i in 1, 2, 3:
print i / 0
except:
print """longer
message"""
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-26 15:11:16
single/double quotes
i backslash
wszędzie:
$ python -c 'exec("import sys\nfor i in range(10): print \"bob\"")'
Znacznie lepiej:
$ python -c '
> import sys
> for i in range(10):
> print "bob"
> '
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-11 08:17:12
Ten skrypt udostępnia interfejs wiersza poleceń podobny do Perla:
Pyliner-skrypt do uruchamiania dowolnego kodu Pythona w wierszu poleceń (przepis Pythona)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-29 11:05:08
Jest jeszcze jedna opcja, sys.stdout.write zwraca None, co powoduje, że lista jest pusta
cat somefile.log|python -c "import sys;[line for line in sys.stdin if sys.stdout.write(line*2)]"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-06 04:30:59
Napisałem do tego prostą stronę internetową. Możesz tam wkleić kod wielowierszowy i przekształcić go w działającą instrukcję jednowierszową.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-10 15:58:31
Jeśli nie chcesz dotykać stdin i symulować tak, jakbyś przeszedł "python cmdfile.py", możesz wykonać następujące czynności z powłoki bash:
$ python <(printf "word=raw_input('Enter word: ')\nimport sys\nfor i in range(5):\n print(word)")
Jak widać, pozwala na używanie stdin do odczytu danych wejściowych. Wewnętrznie powłoka tworzy plik tymczasowy dla zawartości polecenia input.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-07 18:24:46
Kiedy musiałem to zrobić, używam
python -c "$(echo -e "import sys\nsys.stdout.write('Hello World!\\\n')")"
Zwróć uwagę na potrójny ukośnik wsteczny dla nowej linii w sys.stdout.napisz oświadczenie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-07 18:25:25