Удаление строк из файла благодаря переменным из другого файла с помощью AWK или SED

Подробный способ: установить ACCEPTall policy для всех подключений перед сбросом:

iptables -P INPUT    ACCEPT
iptables -P OUTPUT   ACCEPT
iptables -P FORWARD  ACCEPT

Тогда:

iptables -F
1
25.11.2020, 15:42
3 ответа

Вы уже близки, только не хватает нескольких незначительных моментов:

  • Вам нужно добавить data.txtв качестве аргумента к вашему вызову awk, иначе этот файл не будет обработан.
  • В настоящее время вы регистрируете всю строку в keys.txtв базе данных удаления, поэтому вам следует ограничить это вторым полем($2вместо$0).
  • Вы используете if ($0 ~ var), чтобы проверить, следует ли исключить строку в data.txt. Здесь также следует сравнивать только второе поле строки и использовать точное соответствие(==)вместо соответствия регулярному выражению, чтобы защититься от ситуаций, в которых ваши ключи могут содержать специальные символы для регулярных выражений.
  • Вы печатаете из awk, что на самом деле вам не нужно. Вместо этого вы можете перенаправить вывод.

Итак, с небольшими изменениями:

awk 'NR==FNR{pattern[$2];next} !($2 in pattern)' keys.txt data.txt > GoodFile.txt

Это зарегистрирует второй столбец каждой строки в keys.txtв массиве pattern, но больше ничего не сделает для этого файла. Для data.txtбудет достигнута точка, в которой условие !($2 in pattern)оценивается для каждой строки. Если условие оценивается как «истина» (, то есть второй столбец строки , а не среди индексов массива pattern), будет напечатана текущая строка.

6
18.03.2021, 22:47

Первая проблема в вашем скрипте:

NR == FNR {pattern[$0]; next}

Вы используете всю строку в качестве ключа для массива pattern, но вам нужно только второе поле. Вам не нужны оба nextи getline, все, что вам нужно, это nextдля перехода к следующей строке. Вы также забыли передать второй файл в качестве входных данных. Наконец, вам нужно указать имя файла в кавычках, так как это просто строка, а не переменная. Исправление этих двух ошибок дает:

awk '
    NR == FNR {pattern[$2]; next}
    {
        for (var in pattern) {
            if ($0 ~ var) {
                getline
                next
            }
        }
        print >> "GoodFile.txt"
    }
' keys.txt data.txt

Итак, вы уверены, что хотите >>там? Это означает, что awkне перезапишет ничего из того, что уже было в файле (вывода предыдущего запуска, например ). Вам не нужен >>, если вы просто хотите, чтобы awkне перезаписывал свой собственный вывод из одного запуска, >достаточно. Вам нужно только >>, если вы хотите сохранить данные предыдущих запусков, чего, я подозреваю, у вас нет.

Кроме того, исходя из ваших данных, вы на самом деле не хотите проверять всю строку. Вы просто хотите пропустить строки в data.txt, второе поле которых совпадает со вторым полем из keys.txt. Если это так, это было бы намного эффективнее, особенно для больших файлов :

.
awk '
    NR == FNR {pattern[$2]; next}
    {
        if ($2 in pattern) {
            next
        }
        print > "GoodFile.txt"
    }
' keys.txt data.txt

Или эквивалентно, но более кратко:

awk '
    NR == FNR {pattern[$2]; next}
    {
        if (!($2 in pattern) {
            print > "GoodFile.txt"
        }
    }
' keys.txt data.txt
5
18.03.2021, 22:47

GNU sedс включенным расширенным режимом регулярных выражений -Eи отключенным пространством шаблонов автопечати-n

$ sed -En '
    /^\S+\s+(\S+)$/{
      s//\1/;H;d
    }
    G
    /^\S+\s+(\S+)\s.*\n\1(\n|$)/!P
' keys.txt data.txt

Предположим, что в файле ключей два поля, а в файле данных больше двух.

В качестве первого шага мы сохраняем в блоке 2-е поле файла keys.txt. Затем при чтении файла data.txt мы добавляем ключи к текущей записи файла data.txt и сравниваем, можно ли увидеть второе поле данных где-либо среди ключей. Только если не найдено, мы печатаем данные.

0
18.03.2021, 22:47

Теги

Похожие вопросы