Удалить строки из файла на основе шаблонов в другом файле, которые могут частично соответствовать определенному столбцу в первом файле.

Отредактируйте /etc/resolvconf/update. d/libc следующую строку

[ "$N" = 3 ] && return 0

To

[ "$N" = 4 ] && return 0

Теперь вы можете вставить 4 сервера имен в /etc/network/interfaces, вставьте строку в ваш интерфейс

dns-nameservers x.x.x.x y.y.y.y a.a.a.a b.b.b.b
1
28.01.2019, 08:59
2 ответа

Ответ Иниана отлично работает, когда file2состоит всего из одной строки, и это хорошее начало для более общего ответа. Но я верю, что

awk 'FNR == NR { neg[$1]; next } { ok=1; for (i in neg) if ($2 ~ i) ok=0; if (ok) print }' file2 FS="," file1

будет делать то, что вы хотите в целом. Как и ваш ответ, он начинается с чтения file2и сохранения его содержимого. (шаблоны, которые вы хотите удалить изfile)в массиве. Как и ответ Иниана, он читается как file1. Для каждой строки в file1он перебирает шаблоны из file2. Мы предполагаем, что линия в порядке; если он соответствует какому-либо образцу, то это не нормально. Если после проверки всех шаблонов все еще в порядке, мы печатаем его.


Но я поставил FS=","как аргумент между file2и file1просто потому, что так поступил Иниан. Неважно, какой разделитель f поля s мы используем, когда читаем file2, до тех пор, пока он там не появляется — и file2не содержит запятых. Таким образом, мы могли бы немного упростить вышеизложенное указав разделитель полей «обычным» способом — с опцией -Fв начале команды:

awk -F, 'FNR == NR { neg[$1]; next } { ok=1; for (i in neg) if ($2 ~ i) ok=0; if (ok) print }' file2 file1

Вы можете использовать -F",", если хотите; они эквивалентны.


Тест FNR == NRнастолько популярен и распространен что мы используем его, не задумываясь. FNR— это номер строки (, также известный как номер записи)в текущем файле, а NR— это номер строки для всех входных данных. Так, например,

$ cat cats
Felix
Garfield
Heathcliff

$ cat dogs
Lassie
Marmaduke
Snoopy

$ awk '{ print FNR, NR, $0 }' cats dogs
1 1 Felix
2 2 Garfield
3 3 Heathcliff
1 4 Lassie
2 5 Marmaduke
3 6 Snoopy

… и поэтому FNRи NRравны для каждой строки первого обрабатываемого файла, а не в последующем файле (s ). Итак, мы используем FNR == NR, чтобы проверить, обрабатываем ли мы первый файл.

Но на самом деле это плохая практика. Что делать, если первый файл пуст?

$ cat unicorns

$ wc unicorns
      0       0       0 unicorns

$ awk '{ print FNR, NR, $0 }' unicorns dogs
1 1 Lassie
2 2 Marmaduke
3 3 Snoopy

FNR == NRверно для первого файла , в котором действительно есть данные . Если твой file2никогда не будет пустым, вы можете уйти, игнорируя эту проблему. Но, исходя из определения вашей проблемы, если file2пусто, вывод должен быть весь из file1, потому что мы ничего не удаляем. Но если вы запустите приведенную выше команду с пустым file2, вы получите без вывода, потому что awkдумает, что читает первый файл (file2) когда он на самом деле читает второй файл (file1).

Более безопасный способ сделать это — поместить присваивание между аргументами файла:

awk -F, 'FILE != 2 { neg[$1]; next } { ok=1; for (i in neg) if ($2 ~ i) ok=0; if (ok) print }' file2 FILE=2 file1

Вопрос немного двусмысленный. Что означает «частичное совпадение», точно ? Иниан решил интерпретировать это в том смысле, что вопрос предполагает — вроде  grep. Если любое значение из file2соответствует значению из второго столбца file1как регулярное выражение, затем удалите эту строку file1. Но есть две проблемы с этим.

  1. Фактор неожиданности. Я взял файлы в вопросе и добавил

    154376352,"http://sb288eco.tm","example4"
    

    на file1и выполнил свою первую команду. Эта строка "example4"не выводилась, потому чтоsb288.co(из  file2), взятое как регулярное выражение (, где.означает «соответствует любому символу» ), соответствует sb288eco.

    Если вы этого хотите и ожидаете, Вы могли бы также перестать читать это сейчас.

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

Мы можем решить обе вышеуказанные проблемы проверив, является ли строка из file2присутствует в значении из file1с функцией awk index:

awk -F, 'FILE != 2 { neg[$1]; next } { ok=1; for (i in neg) if (index($2,i) > 0) ok=0; if (ok) print }' file2 FILE=2 file1

С учетом вышеизложенного,.в file2соответствует только.в file1, а не любой другой персонаж. Я приглашаю вас проверить вышеизложенное на ваших данных и посмотреть, стало ли оно быстрее.


П.С. Я только что заметил, что вы изменили формат файла так как я опубликовал свой ответ. Изначально вы хотели проверить значения из file2со значениями из второго столбца таблицы file1. Теперь вы, кажется, хотите проверить со значениями изпервого столбцатаблицы file1. Чтобы учесть это изменение, вы должны принять участие в любом из приведенных выше ответов который сравнивает $2с iи изменяет его, чтобы использовать вместо него $1. Или, если вы действительно хотите проверить всю строку из file1, используйте $0.


Итак, вы можете использовать

awk -F, 'FILE != 2 { neg[$1]; next } { ok=1; for (i in neg) if (index($1,i) > 0) ok=0; if (ok) print }' file2 FILE=2 file1

по вашей команде. С разрывами строк для удобочитаемости это

awk -F, 'FILE != 2 { neg[$1]; next }
                   {
                     ok=1
                     for (i in neg)
                             if (index($1,i) > 0) ok=0
                     if (ok) print
                   }' \
        file2 FILE=2 file1
0
27.01.2020, 23:42

То, что у вас есть, выглядит достойной попыткой, но пункт для соответствия регулярному выражению не работает так, как вы хотели. В $2 !~ neg[$1]на file1вы пытаетесь найти значение neg['156398439'], потому что $1будет получено из второго файла, а , а не из первого. Так что ваше состояние никогда не будет соответствовать.

Вы можете сделать что-то вроде приведенного ниже, где вы выполняете сравнение регулярных выражений внутри части действия на file1с помощью цикла

awk 'FNR == NR { neg[$1]; next }{ for ( i in neg ) if ( $2 !~ i) print  }' file2 FS="," file1

Также я не думаю, что FSможно использовать такое сложное регулярное выражение для -ограничения CSV-файлов, помните, что FSопределяет, на какой -ограничитель разбиваться, а не на то, как определять поля. Кажется, у вас было выражение, объясняющее, как должно выглядеть поле. GNU awkпозволяет другой переменной FPATопределять такое регулярное выражение.

Вы можете использовать

awk 'FNR == NR { neg[$1]; next }{ for ( i in neg ) if ( $2 !~ i) print  }' file2 FPAT='([^,]*)|("[^"]+")' file1
1
27.01.2020, 23:42

Теги

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