Czy można skorzystać gawk
z -i inplace
opcji i wydrukować coś stdout
?
Na przykład, jeśli chciałbym zaktualizować plik i jeśli są jakieś zmiany, wydrukuj nazwę pliku i zmienione wiersze stderr
, mógłbym zrobić coś takiego
find -type f -name 'myfiles' -exec gawk -i inplace '{if(gsub(/pat/, "repl")) { print FILENAME > "/proc/self/fd/2" ; print > "/proc/self/fd/2"; } print;}' {} +
ale czy istnieje stdout
zamiast tego sposób użycia lub czystszy sposób wydrukowania tego bloku do alternatywnego strumienia?
find -type f -name 'myfiles' -exec grep -q 'pattern' {} \; -print -exec gawk -i inplace '{do_your_sub_and_print_to_dev/stderr_too}' {} \;
ten sposób, będziesz używał awk tylko do edycji plików, które faktycznie zawierają linie pasujące do tego wzorca.grep
może być. Moim pierwszym instynktem jest uniknięcie konieczności dwukrotnego „przetwarzania” pliku, ale nie byłbym wcale zaskoczony, gdyby mimo to był on szybszy. To po prostu pokazuje, dlaczego mogę ufać mojej odwadze w zadaniach profilowania-print -exec gawk
nie jest już wykonywana) i 2) zatrzyma się przy 1. meczu, więc chyba, że 1. mecz jest w w ostatnim wierszu nadal nie przetwarzasz całego pliku dwa razy (jest to więcej niż 1.X razy). Ponadto, jeśligawk -i inplace
działa tak,sed -i
to i tak edytuje plik na miejscu - tj. Aktualizuje znaczniki czasu, i-węzeł itp., Nawet jeśli nie było nic do edycji ...Odpowiedzi:
Powinieneś użyć
/dev/stderr
lub/dev/fd/2
zamiast/proc/self/fd/2
.gawk
obsługuje/dev/fd/x
i/dev/stderr
sam (niezależnie od tego, czy system ma te pliki, czy nie).Kiedy wykonujesz:
gawk
robi awrite(2, "x\n")
, kiedy to robisz:ponieważ nie traktuje
/proc/self/fd/x
specjalnie, robi:Pierwszy
/proc/self/fd
jest specyficzny dla Linuksa, a na Linuksie są problematyczne. Dwie powyższe wersje nie są równoważne, gdy stderr znajduje się w zwykłym lub innym możliwym do przejrzenia pliku lub w gnieździe (dla którego ten ostatni zawiódłby) (nie wspominając o tym, że marnuje deskryptor pliku).Biorąc to pod uwagę, jeśli chcesz napisać do oryginalnego standardowego interfejsu, musisz zapisać go w innym fd, takim jak:
gawk
przekierowuje standardowe wyjście z plikiem na miejsce. Jest to potrzebne, ponieważ na przykład chcesz:do przechowywania danych
uname
wyjściowych wfile
.źródło
Tylko dla zabawy, alternatywnym podejściem używając tylko POSIX funkcje systemu
find
,sh
,grep
i (przede wszystkim)ex
:(Wszystkie podziały wiersza w powyższym poleceniu są opcjonalne; można je skondensować do jednej linii).
Lub, prawdopodobnie bardziej czytelnie:
:)
(To polecenie jest nieprzetestowane; edycje są mile widziane, jeśli zrobiłem jakieś błędy.)
źródło