Wykonywanie instrukcji wieloliniowych w jednowierszowym wierszu poleceń?


197

Używam Pythona -cdo wykonania pętli jednowierszowej, tj .:

$ python -c "for r in range(10): print 'rob'"

To działa dobrze. Jeśli jednak zaimportuję moduł przed pętlą for, pojawi się błąd składniowy:

$ 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

Masz pomysł, jak to naprawić?

Ważne jest dla mnie, aby mieć to jako jednowierszowe, aby móc dołączyć to do pliku Makefile.


Odpowiedzi:


182

mógłbyś

echo -e "import sys\nfor r in range(10): print 'rob'" | python

lub bez rur:

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

lub odpowiedź @ SilentGhost / odpowiedź @ Crast


Ostatnia opcja działa świetnie z python3 w systemie Windows
Ian Ellis

1
@ RudolfOlah mam nadzieję, że już go znasz, ale tylko w celach informacyjnych, musisz zawinąć instrukcję print dla wersji python3 +, takich jak:python -c "exec(\"import sys\nfor r in range(10): print('rob')\")"
systrigger

@systrigger dzięki, brakowało mi, że myślę, że się spieszyłem i nie zdawałem sobie sprawy, że heh

89

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 tym drugim przypadku usuwane są również wiodące znaki tabulatorów (można uzyskać pewne ustrukturyzowane perspektywy)

zamiast EOF może znieść dowolne słowo znacznikowe, które nie pojawia się w dokumencie tutaj na początku wiersza (patrz także tutaj dokumenty na stronie podręcznika bash lub tutaj ).


9
Miły. Aby przekazać argumenty , po prostu umieść je po <<EOF. Zauważ jednak, że lepiej cytować separator - np. <<'EOF'- aby zabezpieczyć zawartość tego dokumentu przed rozszerzeniem powłoki z góry .
mklement0

56

Problem nie dotyczy tak naprawdę instrukcji importu, ale wszystko, co dzieje się przed pętlą for. A dokładniej, wszystko pojawiające się przed wstawionym blokiem.

Na przykład wszystkie działają:

python -c "import sys; print 'rob'"
python -c "import sys; sys.stdout.write('rob\n')"

Jeśli import będący instrukcją byłby problemem, działałoby to, ale nie:

python -c "__import__('sys'); for r in range(10): print 'rob'"

W bardzo prostym przykładzie możesz przepisać go w następujący sposób:

python -c "import sys; map(lambda x: sys.stdout.write('rob%d\n' % x), range(10))"

Jednak lambdas mogą wykonywać tylko wyrażenia, a nie instrukcje lub wiele instrukcji, więc nadal możesz nie być w stanie zrobić tego, co chcesz. Jednak między wyrażeniami generatora, zrozumieniem listy, lambdami, sys.stdout.write, wbudowanym „mapem” i pewną kreatywną interpolacją ciągów znaków, możesz zrobić potężne jednowierszowe.

Pytanie brzmi: jak daleko chcesz się posunąć i w którym momencie nie jest lepiej napisać mały .pyplik, który zamiast tego wykonuje twój makefile?


31


- Aby ta odpowiedź działała również w Pythonie 3.x , printjest wywoływana jako funkcja : w 3.x działa tylko print('foo') , a 2.x również akceptuje print 'foo'.
- Aby zapoznać się z perspektywą obejmującą wiele platform, która obejmuje system Windows , zobacz pomocną odpowiedź kxr .

W bash, kshlubzsh :

Użyj ciągu ANSI C ( $'...'), który pozwala \nreprezentować znaki nowej linii, które są rozwijane do rzeczywistych linii przed przekazaniem ciągu do python:

python -c $'import sys\nfor r in range(10): print("rob")'

Zwróć uwagę na instrukcje \nmiędzy importi for, aby dokonać podziału linii.

Aby przekazać wartości zmiennej powłoki do takiego polecenia, najbezpieczniej jest użyć argumentów i uzyskać do nich dostęp za sys.argvpomocą skryptu Python:

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 znajduje się omówienie zalet i wad używania podwójnie cytowanego ciągu komend (ucieczka wstępnie przetworzona) z osadzonymi odwołaniami do zmiennych powłoki.

Aby bezpiecznie pracować z $'...'łańcuchami:

  • Podwójne \ wystąpienia w oryginalnym kodzie źródłowym.
    • \<char>Sekwencje - jak \nw tym przypadku, ale również zwykłe podejrzanych, takie jak \t, \r, \b- spienia poprzez $'...'(patrz man printfdla obsługiwanych sekwencji)
  • 'Instancje ucieczki jak \'.

Jeśli musisz pozostać zgodny z POSIX :

Użyj printfz podstawieniem polecenia :

python -c "$(printf %b 'import sys\nfor r in range(10): print("rob")')"

Aby bezpiecznie pracować z tego typu ciągiem:

  • Podwójne \ wystąpienia w oryginalnym kodzie źródłowym.
    • \<char>Sekwencje - jak \nw tym przypadku, ale również zwykłe podejrzanych, takie jak \t, \r, \b- są rozszerzane przez printf(patrz man printfdla obsługiwanych sekwencje).
  • Przekaż pojedynczy ciąg znaków printf %bi 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, w przypadku krótkich skryptów Pythona (jak w tym przypadku) możesz użyć podwójnego cudzysłowu, aby włączyć wartości zmiennych powłoki do swoich skryptów - o ile masz świadomość powiązanych pułapek (patrz następny punkt); np. powłoka rozwija się $HOMEdo 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 za pomocą argumentów i dostęp do nich za pośrednictwem sys.argvPythona; odpowiednikiem powyższego polecenia jest:

        • python -c "$(printf %b 'import sys\nfor r in range(10): print("rob is " + sys.argv[1])')" "$HOME"
    • Korzystanie z ciągu podwójnego cudzysłowu jest wygodniejsze - pozwala na użycie osadzonych pojedynczych cudzysłowów bez ucieczki i osadzonych podwójnych cudzysłowów, ponieważ \"- powoduje również, że ciąg podlega interpretacji przez powłokę , co może, ale nie musi, być intencją; $a `znaki w kodzie źródłowym, które nie są przeznaczone dla powłoki, mogą powodować błąd składniowy lub nieoczekiwanie zmieniać ciąg.

      • Dodatkowo \przeszkadza własne przetwarzanie powłoki w łańcuchach cudzysłowów; na przykład, aby Python wygenerował dosłowny wynik ro\b, musisz go przekazać ro\\b; z '...'ciągiem powłoki i podwójnymi \ instancjami 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 "..."ciągiem powłoki:
        python -c "$(printf %b "import sys\nprint('ro\\\\bs')")" # !! INCORRECT: 'rs'
        Powłoka interpretuje zarówno "\b" i "\\b"dosłownie \b, wymagając oszałamiającej liczby dodatkowych \instancji, aby osiągnąć pożądany efekt:
        python -c "$(printf %b "import sys\nprint('ro\\\\\\\\bs')")"

Aby przekazać kodstdin zamiast -c:

Uwaga: skupiam się tutaj na rozwiązaniach jednowierszowych ; Odpowiedź xorho za pokazuje, jak używać multi-line, tu-dokumentu - pamiętaj, aby zacytować separator jednak; np. <<'EOF'chyba, że ​​wyraźnie chcesz, aby powłoka rozszerzyła łańcuch z przodu (co jest objęte zastrzeżeniami wymienionymi powyżej).


W bash, kshlubzsh :

Połącz ciąg ANSI cytowany w C ( $'...') z ciągiem tutaj ( <<<...):

python - <<<$'import sys\nfor r in range(10): print("rob")'

-mówi pythonjawnie czytać ze standardowego wejścia (co robi domyślnie). -jest w tym przypadku opcjonalny, ale jeśli chcesz również przekazać argumenty do skryptów, potrzebujesz go, aby ujednoznacznić argument z nazwy pliku skryptu:

python - 'rob' <<<$'import sys\nfor r in range(10): print(sys.argv[1])'

Jeśli musisz pozostać zgodny z POSIX :

Użyj printfjak wyżej, ale z potokiem , aby przekazać dane wyjściowe 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'

2
To powinna być wybrana odpowiedź!
debiut

1
To również działa i jest prawdopodobnie najlepszą odpowiedzią, ponieważ zawiera pełne wyjaśnienie, brawo!

22

Masz pomysł, jak to naprawić?

Twój problem wynika z faktu, że oddzielone przez Python instrukcje ;mogą być tylko „małymi instrukcjami”, które są jednowierszowe. Z pliku gramatyki w dokumentach Pythona :

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)

Instrukcje złożone nie mogą być zawarte w tym samym wierszu z innymi instrukcjami za pomocą średników - dlatego robienie tego z -cflagą staje się bardzo niewygodne.

Podczas demonstrowania Pythona w środowisku powłoki bash bardzo przydatne jest dołączanie instrukcji złożonych. Jedynym prostym sposobem na niezawodne wykonanie tego jest użycie heredoków (rzecz powłoki posix).

Heredocs

Użyj heredoc (utworzone <<) i Pythona opcji interfejsu wiersza poleceń , -:

$ 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 następującego -po <<(the <<-) pozwala używać tabulatorów do wcięcia (Stackoverflow konwertuje tabulatory na spacje, więc wciąłem 8 spacji, aby to podkreślić). Wiodące zakładki zostaną usunięte.

Możesz to zrobić bez zakładek za pomocą <<:

$ python - << "EOF"
import sys
for r in range(10):
    print('rob')
EOF

Umieszczanie cudzysłowów EOFzapobiega rozszerzaniu parametrów i arytmetyki . Dzięki temu heredoc jest bardziej wytrzymały.

Bash ciągi wieloliniowe

Jeśli użyjesz podwójnego cudzysłowu, otrzymasz rozszerzenie powłoki:

$ python -c "
> import sys
> for p in '$PATH'.split(':'):
>     print(p)
> "
/usr/sbin
/usr/bin
/sbin
/bin
...

Aby uniknąć rozszerzenia powłoki, użyj cudzysłowów:

$ python -c '
> import sys
> for p in "$PATH".split(":"):
>     print(p)
> '
$PATH

Zauważ, że w Pythonie musimy zamienić znaki cudzysłowu na literały - w zasadzie nie możemy używać znaku cudzysłowu interpretowanego przez BASH. Możemy je zamieniać, tak jak w Pythonie - ale to już wygląda dość mylące, dlatego nie polecam tego:

$ python -c '
import sys
for p in "'"$PATH"'".split(":"):
    print(p)
'
/usr/sbin
/usr/bin
/sbin
/bin
...

Krytyka zaakceptowanej odpowiedzi (i innych)

Nie jest to zbyt czytelne:

echo -e "import sys\nfor r in range(10): print 'rob'" | python

Niezbyt czytelny i dodatkowo trudny do debugowania w przypadku błędu:

python -c "exec(\"import sys\\nfor r in range(10): print 'rob'\")"

Być może nieco bardziej czytelny, ale wciąż dość brzydki:

(echo "import sys" ; echo "for r in range(10): print 'rob'") | python

Będziesz miał zły czas, jeśli masz "w swoim pytonie:

$ python -c "import sys
> for r in range(10): print 'rob'"

Nie nadużywaj mapani nie wymieniaj wyrażeń w celu uzyskania pętli for:

python -c "import sys; map(lambda x: sys.stdout.write('rob%d\n' % x), range(10))"

Wszystkie są smutne i złe. Nie rób ich.


3
++ dla informacji gramatycznych; (nierozwijający się) tutaj-doc jest poręcznym i najsolidniejszym rozwiązaniem, ale oczywiście nie jest jednostronny. Jeśli rozwiązanie pojedyncza linia jest koniecznością, używając ANSI C-cudzysłowie ( bash, kshlub zsh) jest rozsądne rozwiązanie: python -c $'import sys\nfor r in range(10): print(\'rob\')'(musisz się martwić tylko o ucieczce, apostrofów (których można uniknąć za pomocą cudzysłowów) i ukośniki odwrotne).
mklement0

14

po prostu użyj return i wpisz go w następnym wierszu:

user@host:~$ python -c "import sys
> for r in range(10): print 'rob'"
rob
rob
...

6
Poważnie, skręcisz coś, jeśli będziesz to robić dalej. python $(srcdir)/myscript.pydla wielkiej sprawiedliwości.
Jason Orendorff,

10

$ python2.6 -c "import sys; [sys.stdout.write('rob\n') for r in range(10)]"

Działa w porządku. Użyj „[]”, aby wstawić pętlę for.


9

Problem nie dotyczy importoświadczenia. Problem polega na tym, że instrukcje przepływu sterowania nie działają wbudowane w komendzie python. Zastąp to importoświadczenie innym oświadczeniem, a zobaczysz ten sam problem.

Pomyśl o tym: python nie może wstawić wszystkiego. Wykorzystuje wcięcia do grupowania przepływu sterowania.


7

Jeśli twój system jest zgodny z Posix.2, powinien dostarczyć printfnarzędzie:

$ printf "print 'zap'\nfor r in range(3): print 'rob'" | python
zap
rob
rob
rob

2
Dobre rozwiązanie, ale sugeruję użycie w printf %b '...' | pythoncelu zwiększenia niezawodności, ponieważ zapobiega printfinterpretacji sekwencji takich jak %d(specyfikatory formatu) w ciągu wejściowym. Ponadto, chyba że wyraźnie chcesz zastosować rozszerzenia powłoki do łańcucha poleceń Pythona z góry (co może być mylące), lepiej użyć '(pojedynczych cudzysłowów) do zewnętrznego cytowania, aby uniknąć zarówno rozszerzeń, jak i przetwarzania luzu, które stosuje powłoka do łańcuchów cudzysłowów.
mklement0

5

single/double quotesi backslashwszędzie:

$ python -c 'exec("import sys\nfor i in range(10): print \"bob\"")'

Dużo lepiej:

$ python -c '
> import sys
> for i in range(10):
>   print "bob"
> '

więc. wiele. lepszy.
Marc

4

(odpowiedział 23 listopada 2010 o 19:48) Nie jestem naprawdę wielkim Pythonem - ale raz znalazłem tę składnię, zapomniałem skąd, więc pomyślałem, że ją udokumentuję:

jeśli użyjesz sys.stdout.writezamiast print( różnica polega na tym, że sys.stdout.writeprzyjmuje argumenty jako funkcję, w nawiasach - podczas printgdy nie ), to w przypadku jednowierszowego można uniknąć odwrócenia kolejności polecenia i forusunięcia średnika, i zawarcie polecenia w nawiasach kwadratowych, tj .:

python -c "import sys; [sys.stdout.write('rob\n') for r in range(10)]"

Nie mam pojęcia, jak ta składnia zostanie wywołana w Pythonie :)

Mam nadzieję że to pomoże,

Twoje zdrowie!


(EDYCJA Wt 9 kwietnia 20:57:30 2013) Cóż, myślę, że w końcu znalazłem, o co chodzi w tych nawiasach kwadratowych w linijkach ; są „listami” (najwyraźniej); najpierw zwróć uwagę na 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>

Zatem polecenie w okrągłych nawiasach / nawiasach jest postrzegane jako „obiekt generatora”; jeśli wykonamy „iterację” przez wywołanie next()- wówczas polecenie w nawiasie zostanie wykonane (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 - pamiętaj, że nie musimy dzwonić, next()aby wykonać polecenie, wykonuje się je natychmiast po przypisaniu; Jednak później inspekcja wykaże, że ajest None:

$ echo $STR | python -c "import sys,re; a=[sys.stdout.write(line) for line in sys.stdin]; print a"
abc
[None]

Nie pozostawia to wiele informacji do wyszukiwania, w przypadku nawiasów kwadratowych - ale natknąłem się na tę stronę, którą, jak sądzę, wyjaśnia:

Wskazówki i porady dotyczące języka Python - Pierwsze wydanie - Samouczki dotyczące języka Python | Dream.In.Code :

Jeśli pamiętacie, standardowy format generatora jednowierszowego jest rodzajem pętli jednowierszowej „w” w nawiasach. W ten sposób powstanie iterowalny obiekt „jeden strzał”, który jest obiektem, w którym można iterować tylko w jednym kierunku i którego nie można ponownie użyć po osiągnięciu końca.

„Zrozumienie listy” wygląda prawie tak samo jak zwykły generator jednowierszowy, z tym wyjątkiem, że zwykłe nawiasy kwadratowe - () - są zastępowane nawiasami kwadratowymi - []. Główną zaletą alistycznego rozumienia jest to, że tworzy „listę”, a nie „iteracyjny” obiekt iteracyjny, dzięki czemu można przechodzić przez niego w przód iw tył, dodawać elementy, sortować itp.

I rzeczywiście jest to lista - jest to tylko jej pierwszy element, gdy tylko zostanie wykonany:

$ 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

Zrozumienia list są w inny sposób udokumentowane w 5. Struktury danych: 5.1.4. Zrozumienia list - dokumentacja Python v2.7.4 jako „ Zrozumienia list zapewniają zwięzły sposób tworzenia list”; przypuszczalnie właśnie w tym przypadku obowiązuje ograniczona „wykonywalność” list w jednowierszowych liniach.

Cóż, mam nadzieję, że nie jestem tutaj zbyt daleko od znaku ...

EDYCJA 2: a tutaj jest linia poleceń z jednym wierszem z dwoma nie zagnieżdżonymi pętlami for; oba ujęte w nawiasy kwadratowe „rozumienia 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” bma teraz dwa elementy, ponieważ jej pętla for jawnie uruchomiła się dwukrotnie; jednak wynik sys.stdout.write()w obu przypadkach był (najwyraźniej) None.


4

Ten wariant jest najbardziej przenośny do umieszczania skryptów wieloliniowych w wierszu poleceń w systemie Windows i * nix, py2 / 3, bez potoków:

python -c "exec(\"import sys \nfor r in range(10): print('rob') \")"

(Żaden z innych przykładów tu przedstawionych do tej pory tego nie zrobił)

Neat w systemie 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 na bash / * nix to:

python -c $'import sys \nfor r in range(10): print("rob")'

Ta funkcja zamienia dowolny skrypt wielowierszowy w przenośny wiersz poleceń:

def py2cmdline(script):
    exs = 'exec(%r)' % re.sub('\r\n|\r', '\n', script.rstrip())
    print('python -c "%s"' % exs.replace('"', r'\"'))

Stosowanie:

>>> 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\"\"\"')"

Dane wejściowe były:

print 'AA   A'
try:
 for i in 1, 2, 3:
  print i / 0
except:
 print """longer
message"""

++ dla kąta międzyplatformowego i konwertera. Twoje pierwsze polecenie jest tak dobre, jak to możliwe pod względem przenośności (pomijając PowerShell), ale ostatecznie nie ma jednej, w pełni niezawodnej składni wieloplatformowej, ponieważ potrzeba użycia podwójnych cudzysłowów niesie ryzyko niepożądanego rozszerzenia powłoki, z Windows wymagający zmiany znaczenia innych znaków niż powłoki podobne do POSIX. W programie PowerShell v3 lub nowszym możesz sprawić, by wiersze poleceń działały, wstawiając opcję „stop-parsing” --%przed argumentem ciągu poleceń.
mklement0

@ mklement0 „ niechciane rozszerzenia powłoki ”: cóż, wstawianie rozszerzeń powłoki do czegoś w rodzaju print "path is %%PATH%%"resp. print "path is $PATH"jest zwykle opcją, którą chce się w skrypcie lub wierszu poleceń - chyba że unika się rzeczy, jak zwykle dla platformy. To samo z innymi językami. (Sama składnia Pythona nie sugeruje regularnie używania% i $ w konkurencyjny sposób.)
kxr

Jeśli wstawisz odwołania do zmiennych powłoki bezpośrednio do kodu źródłowego Pythona, z definicji nie będzie on przenośny. Chodzi mi o to, że nawet jeśli zamiast tego konstruujesz odwołania do platformy w oddzielnych zmiennych, które przekazujesz jako argumenty do pojedynczej komendy Pythona „bez powłoki” , to może nie zawsze działać, ponieważ nie możesz zabezpieczyć przenośnie łańcucha cudzysłowu : np. co jeśli potrzebujesz literału $foo w kodzie Pythona? Jeśli uciekniesz od niego, tak jak \$foona korzyść pocisków podobnych do POSIX, cmd.exenadal zobaczysz dodatkowe \ . To może być rzadkie, ale warto o tym wiedzieć.
mklement0

Próbuje to zrobić w programie Windows PowerShell, ale problem polega na tym, że python -c exec („” „...” ”)) nie generuje żadnych danych wyjściowych, bez względu na to, czy kod w ... można wykonać albo nie; Mógłbym tam umieścić bełkot, a wynik byłby taki sam. Wydaje mi się, że skorupa „zjada” zarówno strumienie standardowe, jak i standardowe - jak mogę je wypluć?
Yury


1

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 odwrotny dla nowej linii w instrukcji sys.stdout.write.


Działa to, ale ponieważ używasz echo -e, co jest niestandardowe i wymaga bash, kshlub zshrównie dobrze możesz użyć $'...'łańcucha bezpośrednio, co również upraszcza ucieczkę:python -c $'import sys\nsys.stdout.write("Hello World!\\n")'
mklement0

Ta odpowiedź działa, inne odpowiedzi nie działają dla Python3

1

Chciałem rozwiązania o następujących właściwościach:

  1. Czytelny
  2. Przeczytaj standardowe wejście do przetwarzania danych wyjściowych innych narzędzi

Oba wymagania nie zostały podane w innych odpowiedziach, więc oto jak czytać stdin podczas wykonywania wszystkiego w wierszu poleceń:

grep special_string -r | sort | python3 <(cat <<EOF
import sys
for line in sys.stdin:
    tokens = line.split()
    if len(tokens) == 4:
        print("%-45s %7.3f    %s    %s" % (tokens[0], float(tokens[1]), tokens[2], tokens[3]))
EOF
)

0

jest jeszcze jedna opcja, sys.stdout.write zwraca None, która utrzymuje pustą listę

cat somefile.log | python -c "import sys; [linia dla linii w sys.stdin jeśli sys.stdout.write (linia * 2)]"


0

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życie stdin do odczytu danych wejściowych. Wewnętrznie powłoka tworzy plik tymczasowy dla zawartości polecenia wejściowego.


++ za „nieużywanie” standardowego skryptu z samym skryptem (chociaż -c "$(...)"robi to samo i jest zgodny z POSIX); nadać <(...)konstruktowi nazwę: podstawienie procesu ; działa również w kshi zsh.
mklement0
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.