GNU/Linux >> Znalost Linux >  >> Linux

Hledat textové soubory, kde existují dvě různá slova (jakékoli pořadí, libovolný řádek)?

Hledám způsob, jak prohledávat soubory, kde existují dvě instance slova ve stejném souboru. Až do tohoto okamžiku jsem k vyhledávání používal následující:

find . -exec grep -l "FIND ME" {} ;

Problém, na který narážím, je ten, že pokud mezi „FIND“ a „ME“ není přesně jedna mezera, výsledek hledání soubor nezobrazí. Jak přizpůsobím dřívější vyhledávací řetězec, kde v souboru existují obě slova „FIND“ a „ME“ na rozdíl od „FIND ME“?

Používám AIX.

Přijatá odpověď:

S nástroji GNU:

find . -type f  -exec grep -lZ FIND {} + | xargs -r0 grep -l ME

Můžete to udělat standardně:

find . -type f -exec grep -q FIND {} ; -exec grep -l ME {} ;

Ale to by spustilo až dva grep s na soubor. Abyste se vyhnuli spuštění tolika grep s a stále být přenosný a zároveň povolit jakýkoli znak v názvech souborů, můžete udělat:

convert_to_xargs() {
  sed "s/[[:blank:]"']/\\&/g" | awk '
    {
      if (NR > 1) {
        printf "%s", line
        if (!index($0, "//")) printf "\"
        print ""
      }
      line = $0
    }'
    END { print line }'
}

export LC_ALL=C
find .//. -type f |
  convert_to_xargs |
  xargs grep -l FIND |
  convert_to_xargs |
  xargs grep -l ME

Cílem je převést výstup find do formátu vhodného pro xargs (který očekává prázdné místo (SPC/TAB/NL v C locale, YMMV v jiných locales) oddělený seznam slov, kde jednoduché, dvojité uvozovky a zpětná lomítka mohou uniknout mezerám a navzájem).

Obecně nelze dodatečně zpracovat výstup příkazu find -print , protože odděluje názvy souborů znakem nového řádku a neuniká znaky nového řádku, které se nacházejí v názvech souborů. Pokud například vidíme:

./a
./b

Nemáme žádný způsob, jak zjistit, zda se jedná o jeden soubor s názvem b v adresáři s názvem a<NL>. nebo pokud se jedná o dva soubory a a b v aktuálním adresáři.

Pomocí .//. , protože // nemůže se jinak objevit v cestě k souboru jako výstup pomocí find (protože neexistuje nic takového jako adresář s prázdným názvem a / není povoleno v názvu souboru), víme, že pokud vidíme řádek, který obsahuje // , pak je to první řádek nového souboru. Můžeme tedy použít ten awk příkaz k escapování všech znaků nového řádku kromě těch, které tyto řádky předcházejí.

Vezmeme-li příklad výše, find bude výstup v prvním případě (jeden soubor):

.//a
./b

Které awk unikne do:

.//a
./b

Takže xargs bere to jako jeden argument. A ve druhém případě (dva soubory):

.//a
.//b

Což awk ponechá tak, jak je, takže xargs vidí dva argumenty.

Související:Zapnutý režim myši Tmux neumožňuje vybrat text myší?

Potřebujete LC_ALL=C tak sed , awk (a některé implementace xargs ) pracovat s libovolnými sekvencemi bajtů (i když v národním prostředí uživatele netvoří platné znaky), aby se zjednodušila prázdná definice pouze na SPC a TAB a vyhnout se problémům s různými interpretacemi znaků, jejichž kódování obsahuje kódování zpětného lomítka různými nástroji.


Linux
  1. Porovnat dva sloupce různých souborů a vytisknout, pokud se shodují?

  2. Hledat soubory, jejichž cesty obsahují několik slov bez konkrétního pořadí mezi nimi?

  3. Použijte Najít a najít k vyhledání souborů v Linuxu

  1. Vytvářejte soubory pomocí příkazového řádku v Linuxu

  2. Jak hledat soubory pomocí regulárního výrazu ve skriptu linuxového shellu

  3. linux:hledání souborů typu *.php, které byly nedávno upraveny

  1. Jak přidat čísla řádků do textových souborů v systému Linux

  2. Extrahovat hodnotu mezi dvěma vyhledávacími vzory na stejném řádku?

  3. jak mohu vyhledat soubory a zazipovat je do jednoho souboru zip