grep "hehe" < test.sh
przekierowanie wejścia - działa tylko na jednym pliku, oczywiście, natomiast cat
prac dla dowolnej liczby plików wejściowych.
Rozważmy postaciach:
grep "hehe" $(cat test.sh)
grep "hehe" `cat test.sh`
te odpowiadają w tej dziedzinie; dużo łatwiej jest używać „$(cmd)
” notacji w zagnieżdżonych zastosowań, takich jak:
x=$(dirname $(dirname $(which gcc)))
x=`dirname \`dirname \\\`which gcc\\\`\``
(Daje to podstawowy katalog, w którym zainstalowany jest GCC, w przypadku, gdy zastanawiasz.)
W Przykładowo, co się dzieje, jest to, że treść test.sh
jest odczytywana i dzielona na słowa oddzielone białymi znakami, a każde takie słowo jest dostarczane jako argument do grep
. Od grep
traktuje słowa po "hehe"
(gdzie grep
, oczywiście, nie , nie zobacz podwójne cudzysłowy - i nie są one potrzebne w tym przypadku, z reguły używać pojedynczych cudzysłowów, a nie podwójnych cudzysłowów, zwłaszcza wokół skomplikowanych ciągów takich jak wyrażenia regularne, które często używają metaznaków powłoki) ... Jak już mówiłem, grep
traktuje słowa po "hehe"
jako nazwy plików i próbuje otworzyć każdy plik, zwykle nie działa zawrotnie, ponieważ pliki nie istnieją. Dlatego notacja nie jest odpowiednia w tym kontekście.
Po ponownej analizie pytania można powiedzieć jeszcze więcej - o czym jeszcze nie powiedziano.
Po pierwsze, wiele poleceń Uniksa zaprojektowano tak, aby działały jako "filtry"; odczytują dane wejściowe z niektórych plików, przekształcają je w pewien sposób i zapisują wynik na standardowe wyjście. Takie polecenia są przeznaczone do użycia w obrębie potoków poleceń. Przykłady obejmują:
- kot
- grep
- troff i krewni
- awk (z zastrzeżeniami)
- sed
- rodzaj
Wszystkie te filtry mają taką samą ogólną zachowanie : pobierają opcje wiersza poleceń, aby kontrolować swoje zachowanie, a następnie albo odczytują plik s podane jako argumenty linii poleceń lub, jeśli nie ma takich argumentów, odczytują ich standardowe wejście. Niektóre (np. sort
) mogą mieć opcje kontrolowania, gdzie ich wyjście idzie zamiast standardowego wyjścia, ale jest to stosunkowo rzadkie.
Istnieje kilka czystych filtrów - tr
jest jednym z takich, który ściśle czyta standardowe wejście i zapisuje na standardowe wyjście.
Inne polecenia mają różne zachowania. Eric Raymond zapewnia taksonomię dla typów poleceń w "The Art of UNIX Programming".
Niektóre polecenia generują listy nazw plików na standardowe wyjście - dwie klasyki to ls
i find
.
Czasami należy zastosować wyjście z generatora nazw plików jako argumentów wiersza poleceń dla filtru. Jest program, który robi to automatycznie - jest to xargs
.
Klasycznie, użyłbyś:
find . -name '*.[chyl]' | xargs grep -n magic_name /dev/null
będzie to generować kompletną listę plików z '.c
', '.h
', '.y
' i '.l
' (źródło C, nagłówki rozszerzeń, Yacc i pliki Lex). Gdy lista zostanie odczytana przez xargs
, utworzy wiersze poleceń z grep -n magic_name /dev/null
na początku i każde słowo (oddzielone białą spacją) jako argument.
W dawnych czasach nazwy plików uniksowych nie zawierały spacji. Pod wpływem komputerów Mac i Windows takie przestrzenie są teraz powszechne. Wersje GNU find
i xargs
mają komplementarne możliwości radzenia sobie z tym problemem:
find . -name '*.[chyl]' -print0 | xargs -0 grep -n magic_name /dev/null
Opcja „-print0
” oznacza „nazwy plików drukowania zakończona NUL«\ 0»” (bo tylko znaki, które nie mogą pojawić się w (prostej) nazwie pliku są "/" i NUL, i oczywiście "/" może pojawić się w nazwach ścieżek). Odpowiedni "-0
" mówi, aby wyszukać nazwy zakończone przez NUL zamiast nazw rozdzielanych spacjami.
Twoje pytanie jest trochę mylące - mam nadzieję, że albo przekierowanie wejścia lub po prostu podanie nazwy pliku jako argumentu jest tym, co chciałeś. Z drugiej strony, jeśli pytasz, jak wziąć stdout jednego polecenia i przekazać go do stdin innego polecenia bez użycia potoku ... to jest definicja potoku. – Cascabel