Doskonale znam narzędzie source
(aka .
), które pobierze zawartość z pliku i uruchomi ją w bieżącej powłoce.
Teraz przekształcam tekst w polecenia powłoki, a następnie uruchamiam je w następujący sposób:
$ ls | sed ... | sh
ls
to tylko przypadkowy przykład, oryginalny tekst może być dowolny. sed
także przykład przekształcania tekstu. Ciekawe jest to sh
. Piszczę wszystko, co mam, sh
i to działa.
Mój problem polega na tym, że oznacza to uruchomienie nowej podpowłoki. Wolałbym, aby polecenia były uruchamiane w mojej obecnej powłoce. Jakbym był w stanie zrobić source some-file
, gdybym miał polecenia w pliku tekstowym.
Nie chcę tworzyć pliku tymczasowego, ponieważ jest brudny.
Alternatywnie, chciałbym rozpocząć moją subpowłokę z dokładnie takimi samymi cechami, jak moja obecna powłoka.
aktualizacja
Ok, rozwiązania korzystające z backticka z pewnością działają, ale często muszę to robić, gdy sprawdzam i zmieniam dane wyjściowe, więc wolałbym, aby istniał sposób, aby ostatecznie przekuć wynik na coś.
smutna aktualizacja
Ach, /dev/stdin
rzecz wyglądała tak ładnie, ale w bardziej złożonym przypadku nie działała.
Więc mam to:
find . -type f -iname '*.doc' | ack -v '\.doc$' | perl -pe 's/^((.*)\.doc)$/git mv -f $1 $2.doc/i' | source /dev/stdin
Co zapewnia, że wszystkie .doc
pliki mają małe litery rozszerzenia.
I z którym, nawiasem mówiąc, można sobie poradzić xargs
, ale nie o to chodzi.
find . -type f -iname '*.doc' | ack -v '\.doc$' | perl -pe 's/^((.*)\.doc)$/$1 $2.doc/i' | xargs -L1 git mv
Więc kiedy uruchomię ten pierwszy, od razu się zamknie, nic się nie dzieje.
Odpowiedzi:
$ ls | sed ... | source /dev/stdin
UPDATE: Działa w bash 4.0, a także w tcsh i dash (jeśli zmienisz
source
na.
). Najwyraźniej był to błąd w bashu 3.2. Z informacji o wydaniu bash 4.0 :źródło
eval "$(sed ...)"
podejście - ale dzięki za informację o błędzie 3.2!Plik
eval
Polecenie istnieje w tym samym celu.eval "$( ls | sed... )"
Więcej z podręcznika basha :
źródło
eval "$( ssh remote-host 'cat ~/.bash_profile' )"
Zauważ, że rzeczywiście używam basha 3.2.Wow, wiem, że to stare pytanie, ale ostatnio napotkałem ten sam problem (tak się tutaj dostałem).
Zresztą - odpowiedź mi się nie podoba
source /dev/stdin
, ale myślę, że znalazłem lepszą. W rzeczywistości jest to zwodniczo proste:echo ls -la | xargs xargs
Fajnie, prawda? Właściwie to nadal nie robi tego, co chcesz, ponieważ jeśli masz wiele wierszy, połączy je w jedno polecenie zamiast uruchamiać każde polecenie osobno. Tak więc rozwiązanie, które znalazłem, to:
-L 1
opcja oznacza użyć (co najwyżej) 1 linia na wykonanie polecenia. Uwaga: jeśli twoja linia kończy się spacją na końcu, zostanie połączona z następną linią! Dlatego upewnij się, że każda linia kończy się spacją.Wreszcie możesz to zrobić
aby zobaczyć, jakie polecenia są wykonywane (-t jest gadatliwe).
Mam nadzieję, że ktoś to przeczyta!
źródło
Spróbuj użyć podstawiania procesu , które zastępuje wynik polecenia plikiem tymczasowym, z którego można następnie pobrać:
source <(echo id)
źródło
echo <(echo id)
podając wynik/dev/fd/12
(12 to przykład)cat <(echo id)
, podając wynikid
, a następniesource <(echo id)
podając ten sam wynik, co po prostu napisanieid
(...)
przekierowana podpowłoka ?Uważam, że to „właściwa odpowiedź” na pytanie:
ls | sed ... | while read line; do $line; done
Oznacza to, że można podłączyć rurę do
while
pętli;read
komend zajmuje jedną linię z jegostdin
i przypisuje go do zmiennej$line
.$line
następnie staje się poleceniem wykonywanym w pętli; i kontynuuje, dopóki nie będzie żadnych dalszych wierszy na wejściu.To nadal nie zadziała z niektórymi strukturami sterującymi (takimi jak inna pętla), ale w tym przypadku pasuje do rachunku.
źródło
Wydaje mi się, że
ls | sed ... | source -
byłoby ładniej, ale niestetysource
nie rozumiem, co-
to znaczystdin
.źródło
Myślę, że twoim rozwiązaniem jest zastępowanie poleceń lewymi znakami: http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html
Patrz sekcja 3.4.5
źródło
$( )
preferowana może być składnia.Aby użyć rozwiązania mark4o w bash 3.2 (macos), zamiast potoków, jak w tym przykładzie, można użyć ciągu tutaj:
. /dev/stdin <<< "$(grep '^alias' ~/.profile)"
źródło
Dlaczego więc nie użyć
source
?$ ls | sed ... > out.sh ; source out.sh
źródło