Можно ли разбить текстовый файл на основе поиска по шаблону? - PullRequest
0 голосов
/ 22 июня 2019

У меня есть текстовый файл, и я хочу разделить этот файл, удалив строки, содержащие определенные слова.Например:

remove those lines containing the word 'fish' from the file and output them into fish.txt

remove those lines containing the word 'cat' from the file and output them into cat.txt

...

Удобно ли это сделать в vim, grep или другими простыми способами?Это не должно быть сделано в одном потоке, если это сложно.Для каждого шаблона это можно сделать по одному.

Ответы [ 5 ]

2 голосов
/ 22 июня 2019

Вы можете использовать эту функцию Vim:

function! DeleteWord()
  let word=input("word to delete: ")
  let file=word.".txt"
  redraw
  silent! exe 'g/\<'.word.'\>/.w! >> '.file.' | d'
  echo "wrote to file ".file
endfunction
nnoremap <c-y> :call DeleteWord()<cr>

Это можно вызвать с помощью Ctrl+y.Больше информации на страницах справки: :w_a, :. и :g.

2 голосов
/ 22 июня 2019

awk решение (при условии, что строка может содержать fish или cat, но не оба):

Образец input.txt содержимое:

some text1
fish 1
some text 2
text cat 1
some text 3
some text 4
text fish 2
testx cat 2 cat 3
text text text
text ---- fish 3 ----
*** text ***

awk '/fish|cat/{ print > ($0~/fish/? "fish" : "cat")".txt"; next}1' input.txt > /tmp/_fc.txt \
&& mv /tmp/_fc.txt input.txt

Результаты:

$ cat input.txt
some text1
some text 2
some text 3
some text 4
text text text
*** text ***

$ cat fish.txt
fish 1
text fish 2
text ---- fish 3 ----

$ cat cat.txt
text cat 1
testx cat 2 cat 3
1 голос
/ 22 июня 2019

С помощью gnu awk вы можете сделать это

awk 'match($0,/(cat|dog|fish)/,a) {print >a[1]".txt";next} {print >"rest.txt"}' file

Затем в качестве имени файла будет использована группа захвата #1.Вы можете задавать столько слов, сколько хотите, и для каждого слова в группе создается новый файл, если он соответствует.Затем остальное печатается в rest.txt

. Это также будет работать с регулярным выражением.Можно использовать более сложное выражение.
Оно сломается, если в одной строке будет более одного триггерного слова.


Та же версия awk, что и у RomanPerekhrest, но некоторые легче читаются ипроще для расширения.

awk '/fish/ {print > "fish.txt"; next} /cat/ {print > "cat.txt"; next} /dog/ {print > "dog.txt"; next} 1' input.txt > /
/tmp/_fc.txt > && mv /tmp/_fc.txt input.txt

Еще лучшее форматирование:

awk '
    /fish/ {print > "fish.txt"; next} 
    /cat/ {print > "cat.txt"; next} 
    /dog/ {print > "dog.txt"; next} 
    1' input.txt > /tmp/_fc.txt \
&& mv /tmp/_fc.txt input.txt
0 голосов
/ 22 июня 2019

Поскольку grep происходит из команды * (1001 *) vi (m), для ответов используются оба:

Из vim:

:global/\<word\>/.write! >>word.txt | delete
...

Grep:

grep 'word' > word.txt
...
grep -v 'words|to|delete' file > remaining

\v - очень магический режим; -v инвертирует совпадения.

0 голосов
/ 22 июня 2019

Я бы хотел расширить @Jotne на более общий случай, предоставив список слов в качестве входных данных для сценария.

Снова со скриптом awk.

script.awk:

BEGIN {split(wordsList, words);} # get all the words into an array
{
    foundWord = 0;
    for (i in words) { # for each word
        if (match($0, words[i])) { # if found a word in input line
            print $0 > words[i]"s.txt"; # redirect input line to coresponding output file
            foundWord++; # mark word as found
        }
    }
}
(foundWord == 0) # output unmarked words

Выполнение скрипта со списком слов, заданным из $list varaible:

list="cat dog lion fly"
awk -v wordsList="$list" -f script.awk input.txt > input.cleared.txt

Очищено / очищено input.txt предоставляется в input.cleared.txt

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...