Bash
Zastąpienie procesu
Szukaj…
Uwagi
Podstawienie procesu to forma przekierowania, w której wejście lub wyjście procesu (pewna sekwencja poleceń) pojawia się jako plik tymczasowy.
Porównaj dwa pliki z Internetu
Poniżej porównano dwa pliki z diff
przy użyciu podstawiania procesów zamiast tworzenia plików tymczasowych.
diff <(curl http://www.example.com/page1) <(curl http://www.example.com/page2)
Wprowadź pętlę while do wyjścia polecenia
To zasila while
pętli z wyjściem grep
polecenia:
while IFS=":" read -r user _
do
# "$user" holds the username in /etc/passwd
done < <(grep "hello" /etc/passwd)
Za pomocą polecenia wklej
# Process substitution with paste command is common
# To compare the contents of two directories
paste <( ls /path/to/directory1 ) <( ls /path/to/directory1 )
Łączenie plików
Powszechnie wiadomo, że nie można używać tego samego pliku do wprowadzania i wypisywania w tym samym poleceniu. Na przykład,
$ cat header.txt body.txt >body.txt
nie robi tego, co chcesz. Zanim cat
odczyta body.txt
, został już skrócony przez przekierowanie i jest pusty. Ostateczny wynik będzie taki, że body.txt
będzie zawierało tylko zawartość header.txt
.
Można pomyśleć, aby tego uniknąć, zastępując proces, czyli polecenie
$ cat header.txt <(cat body.txt) > body.txt
wymusi body.txt
oryginalnej zawartości body.txt
w jakimś buforze, zanim plik zostanie obcięty przez przekierowanie. To nie działa cat
w nawiasach zaczyna czytać plik dopiero po skonfigurowaniu wszystkich deskryptorów plików, podobnie jak zewnętrzny. W tym przypadku nie ma sensu próbować stosować zastępowania procesów.
Jedynym sposobem na dołączenie pliku do innego pliku jest utworzenie pliku pośredniego:
$ cat header.txt body.txt >body.txt.new
$ mv body.txt.new body.txt
co robią sed
perl
lub podobne programy pod dywan, gdy są wywoływane z opcją edycji na miejscu (zwykle -i
).
Przesyłaj strumieniowo plik przez wiele programów jednocześnie
Zlicza to liczbę wierszy w dużym pliku z wc -l
, jednocześnie kompresując go za pomocą gzip
. Oba działają jednocześnie.
tee >(wc -l >&2) < bigfile | gzip > bigfile.gz
Zwykle tee
zapisuje dane wejściowe w jednym lub kilku plikach (i standardowym wyjściu). Możemy pisać do poleceń zamiast plików za pomocą tee >(command)
.
Tutaj polecenie wc -l >&2
zlicza linie odczytane z tee
(które z kolei czyta z bigfile
). (Liczba linii jest wysyłana do stderr ( >&2
), aby uniknąć pomieszania z wejściem do gzip
.) Stdout tee
jest jednocześnie podawany do gzip
.
Aby uniknąć użycia podpowłoki
Jednym z głównych aspektów podstawiania procesów jest to, że pozwala nam to uniknąć używania podpowłoki podczas przesyłania poleceń z powłoki.
Można to wykazać na prostym przykładzie poniżej. Mam następujące pliki w moim bieżącym folderze:
$ find . -maxdepth 1 -type f -print
foo bar zoo foobar foozoo barzoo
Jeśli potokuję do pętli while
/ read
, która zwiększa licznik w następujący sposób:
count=0
find . -maxdepth 1 -type f -print | while IFS= read -r _; do
((count++))
done
$count
nie zawiera teraz 6
, ponieważ został zmodyfikowany w kontekście podpowłoki. Każde z poniższych poleceń jest uruchamiane w kontekście podpowłoki, a zakres zmiennych używanych w nim jest tracony po zakończeniu podpowłoki.
command &
command | command
( command )
Zastąpienie procesu rozwiąże problem, unikając użycia potoku |
operator jak w
count=0
while IFS= read -r _; do
((count++))
done < <(find . -maxdepth 1 -type f -print)
Spowoduje to zachowanie wartości zmiennej count
ponieważ nie są wywoływane żadne podpowłoki.