Bash 4.2 na CentOS 6.5:
W mojej ~/.bash_profile
mam kilka aliasów, w tym:
alias grep='grep -n --color=always'
dzięki czemu mogę automatycznie wyróżniać kolory i drukować numery linii automatycznie podczas działania grep
. Jeśli uruchomię następujące czynności, wyróżnianie działa zgodnie z oczekiwaniami:
$ grep -Re 'regex_here' *.py
Jednak kiedy uruchomiłem to niedawno:
$ find . -name '*.py' | xargs grep -E 'regex_here'
wyniki nie zostały podświetlone, a numery wierszy nie zostały wydrukowane, co zmusiło mnie do powrotu i wyraźnego dodania -n --color=always
do grep
polecenia.
- Czy
xargs
nie odczytuje aliasów w środowisku? - Jeśli nie, czy istnieje sposób, aby to zrobić?
xargs
poleceniu. Próbuję się dowiedzieć, czy istnieje sposób, aby bezpośrednio wywołać mój aliasxargs
.export GREP_OPTIONS='-n --color=always'
wcześniej przed komendą xargs?.bash_profile
. Napisz odpowiedź ...Odpowiedzi:
Alias jest wewnętrzny dla powłoki, w której jest zdefiniowany. Nie jest widoczny dla innych procesów. To samo dotyczy funkcji powłoki.
xargs
jest osobną aplikacją, która nie jest powłoką, więc nie ma pojęcia aliasów ani funkcji.Możesz zmusić xargs do wywoływania powłoki zamiast wywoływania
grep
bezpośrednio. Jednak samo wywołanie powłoki nie wystarczy, musisz również zdefiniować alias w tej powłoce. Jeśli alias jest zdefiniowany w twoim.bashrc
pliku, możesz pobrać ten plik; może to jednak nie działać w przypadku.bashrc
wykonywania innych zadań, które nie mają sensu w powłoce nieinteraktywnej.Uważaj na zawiłości cytowania zagnieżdżonego podczas wpisywania wyrażenia regularnego. Możesz uprościć swoje życie, przekazując wyrażenie regularne jako parametr do powłoki.
Możesz wykonać wyszukiwanie aliasu jawnie. Wtedy
xargs
zobaczyszgrep -n --color=always
.W Zsh:
Nawiasem mówiąc, zauważ, że
find … | xargs …
łamie nazwy plików zawierające spacje (między innymi) . Możesz to naprawić, zmieniając rekordy rozdzielane wartościami zerowymi:lub za pomocą
-exec
:Zamiast dzwonić
find
, możesz zrobić wszystko całkowicie w powłoce. Wzorzec glob**/
rekurencyjnie przechodzi przez katalogi. W bash musisz najpierw uruchomićshopt -s globstar
ten wzorzec glob.Ma to kilka ograniczeń:
**/
powtarza się w symboliczne linki do katalogów.Innym podejściem jest stosowanie substytucji procesu, jak sugeruje MariusMatutiae .
Jest to przydatne, gdy
**/
nie ma zastosowania: dlafind
wyrażeń złożonych lub w bash ≤4,2, gdy nie chcesz powtarzać się pod symbolicznymi linkami. Zauważ, że powoduje to uszkodzenie nazw plików zawierających spacje; obejściem tego problemu jest ustawienieIFS
i wyłączenie globowania , ale zaczyna się ono nieco komplikować :źródło
Posługiwać się
alias xargs='xargs '
źródło
sudo
…Proszę wziąć to za przykład innego podejścia, którego nie mogę znaleźć w powiązanym pytaniu SO :
Możesz napisać funkcję otoki, dla
xargs
której sprawdza, czy pierwszy argument jest aliasem, a jeśli tak, odpowiednio go rozwiń.Oto kod, który robi dokładnie to, ale niestety wymaga powłoki Z, a zatem nie uruchamia 1: 1 z bash (i szczerze mówiąc, nie jestem przyzwyczajony do bashowania wystarczającego do przeniesienia go):
Dowód, że to działa:
źródło
Prostszym i bardziej eleganckim rozwiązaniem jest stosowanie zastępowania procesów :
Nie tworzy nowej powłoki, jak potok, co oznacza, że nadal znajdujesz się w oryginalnej powłoce, w której zdefiniowany jest alias, a wynik jest dokładnie taki, jak chcesz.
Uważaj tylko, aby nie pozostawić spacji między przekierowaniem a nawiasami, w przeciwnym razie bash wygeneruje błąd. Według mojej najlepszej wiedzy podstawianie procesów jest obsługiwane przez Bash, Zsh, Ksh {88,93}, ale nie przez pdksh (powiedziano mi, że powinno to być jeszcze nie ).
źródło
find
poleceń, choć należy uważać, aby nie działały one na spacje i nie można tego naprawić tak łatwo, jakfind | xargs
to możliwe (przez przełączenie na-print0
i-0
lub użycie-exec
). W stosownych przypadkach**/
jest prostszy i bardziej niezawodny.grep odczyta zestaw domyślnych opcji ze zmiennej środowiskowej GREP_OPTIONS. Jeśli umieścisz
w twoim .bashrc zmienna zostanie przekazana do podpowłok i uzyskasz oczekiwane wyniki.
źródło
--line-number
albo--color=always
wGREP_OPTIONS
chyba, że to tylko dla jednego polecenia, to przełamać wiele skryptów.--color=auto
jest w porządku mieć to i to wszystko. Umieszczenie tego wiersza w tobie.bashrc
złamie wiele rzeczy./etc/init.d/cron
w moim systemie:value=`egrep "^${var}=" "$ENV_FILE" | tail -n1 | cut -d= -f2`
. Lub/usr/bin/pdfjam
:pdftitl=`printf "%s" "$PDFinfo" | grep -e … | sed -e …`
. Alias nie stanowi problemu, ponieważ nie jest widoczny w skryptach.GREP_OPTIONS
przerwy przewidywalność bardzo źle, z wyjątkiem kilku opcji, takich jak--color=auto
(co jest, co zostało zaprojektowane dla).