Как удалить строки из текстового файла, содержащего определенные слова, через терминал?

72

Как удалить все строки из текстового файла, содержащего слова «кошка» и «крыса»?

PersonX
источник
Это звучит подозрительно, как домашнее задание. Пожалуйста, не забудьте приписать свой ответ приятным людям из Askubuntu.
zwets
Что является частью большого проекта, я новичок в среде Linux.
PersonX

Ответы:

100

grep подход

Чтобы создать копию файла без строк, совпадающих с «кошкой» или «крысой», можно использовать метод grepreverse ( -v) и с параметром целого слова ( -w).

grep -vwE "(cat|rat)" sourcefile > destinationfile

Параметр «целое слово» гарантирует, что он не будет совпадать catsили, gratefulнапример. Перенаправление вывода вашей оболочки используется ( >) для записи его в новый файл. Нам нужна -Eопция для включения расширенных регулярных выражений для (one|other)синтаксиса.

sed подход

В качестве альтернативы, чтобы удалить строки на месте можно использовать sed -i:

sed -i "/\b\(cat\|rat\)\b/d" filename

Эти \bграницы множества слов и dоперация удаляют строку , соответствующее выражение между косой чертой. catи ratоба соответствуют (one|other)синтаксису, который мы, очевидно, должны избежать с помощью обратной косой черты

Совет: используйте sedбез -iоператора, чтобы проверить вывод команды перед перезаписью файла.

(На основе Sed - удалить строку, содержащую определенную строку )

gertvdijk
источник
Интересно, есть ли способ добиться как удаления из исходного файла, так и создания файла со совпадениями. Вероятно, нет, но это было бы полезно (например, когда вы получаете файл, который становится слишком большим, вы разделяете его по содержимому).
Шридхар Сарнобат
1
@ Шридхар-Сарнобат О, ты можешь. Используйте тройник и подоболочки, чтобы скопировать стандартный вывод. В одном вы фильтруете, в другом - наоборот. Использование тройника и подоболочек, продемонстрированных в несвязанном сценарии использования, продемонстрированном здесь: blog.g3rt.nl/…
gertvdijk
15

Для проверки только в терминале используйте:

sed '/[cr]at/d' file_name

Чтобы действительно удалить эти строки из файла, используйте:

sed -i '/[cr]at/d' file_name
Раду Рэдяну
источник
5

Попробуйте vim-way:

ex +"g/[cr]at/d" -scwq file.txt
kenorb
источник
0

Рассмотрим , если у вас есть файл с , file_nameи вы хотите найти мышь , но в то же время несколько строк из мыши , имеющие другие слова , как catи ratи вы не хотите , чтобы увидеть тех , кто в вашем выводе, так что один из способов сделать это -

grep -r mouse file_name | grep -vE "(cat|rat)"
Индраджит Гур
источник
0

портативный способ оболочки

Работает в /bin/sh, который есть dashна Ubuntu, а также ksh, и bash. Немного неловко, что вам приходится писать несколько тестов для каждого слова в caseвыражении, но переносимо. Работает со случаями, когда слово появляется отдельно в строке, в начале, конце строки или в середине строки, и игнорирует, где оно может быть частью другого слова.

#!/bin/sh
line_handler(){
   # $1 is line read, prints to stdout
    case "$1" in
        cat|cat\ *|*\ cat\ *|*\ cat) true;; # do nothing if cat or rat in line
        rat|rat\ *|*\ rat\ *|*\ rat) true;; 
        *) printf "%s\n" "$1"
    esac
}

readlines(){
    # $1 is input file, the rest is words we want to remove
    inputfile="$1"
    shift

    while IFS= read -r line;
    do
        line_handler "$line" "$@"
    done < "$inputfile"
    [ -n "$line" ] && line_handler "$line" 
}

readlines "$@"

И вот как это работает:

$ cat input.txt                                                                                                                                                        
the big big fat cat
the cat who likes milk 
jumped over gray rat
concat 
this is catchy
rat
rational
irrational
$ ./dellines.sh input.txt                                                                                                                                              
concat 
this is catchy
rational
irrational
Сергей Колодяжный
источник