我可以基于模式搜索拆分文本文件吗?

时间:2019-06-22 04:51:38

标签: awk vim grep

我有一个文本文件,我想通过删除包含特定单词的行来拆分此文件。例如:

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或其他一些简单方式方便地完成吗?如果很复杂,则不必一flow而就。对于每种模式,可以一次完成一个。

5 个答案:

答案 0 :(得分:2)

awk解决方案(假设一行可以包含fishcat,但不能同时包含两者):

示例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 :(得分:2)

您可以使用此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 :(得分:1)

通过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

答案 3 :(得分:0)

我想将@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变量给出的单词列表执行脚本:

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

input.txt中提供了清除/清除的input.cleared.txt

答案 4 :(得分:0)

由于grep来自vi(m)的:g/re/p命令,因此可以同时使用以下两种答案:

从vim:

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

Grep:

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

\v是非常神奇的模式; -v反转匹配。