Чтобы проиллюстрировать это, у нас есть два файла:
file1
hello
1_hello
2_hello
world
1_world
2_world
hello1
1_hello1
2_hello1
world1
1_world1
2_world1
file2
This
hello
1_hello
2_hello
is world
1_world
2_world
my
hello1
1_hello1
2_hello1
word
world1
1_world1
2_world1
file
что Я хочу, чтобы итерация первого столбца файла1 и удаление записей, которые соответствуют в файле2, и выводятся как:
This
is
my
word
file
Как я могу продолжить?
Вы можете использовать grep -f FILE для получения паттернов из файла FILE. В вашем случае я рекомендую несколько дополнительных флагов (см. Объяснение ниже) для следующего окончательного вызова grep:
grep -v -x -F -f file1 -- file2
-f FILE - Получить шаблоны из FILE, по одному на строку. -F. Интерпретировать шаблон как список фиксированных строк, разделенных символами новой строки, любой из которых должен быть сопоставлен. -x - выберите только те совпадения, которые точно соответствуют всей строке. (Вы можете удалить эту опцию, если хотите разрешить частично совпадающие строки.) [F9] - инвертировать смысл соответствия, чтобы выбрать несогласованные строки. Источник: документация GNU grep или, альтернативно, ее страница руководства
Все параметры, используемые выше, задаются POSIX и не требуют расширений GNU.
Вы хотите использовать awk для чтения файла1 и запомнить все его слова. Затем прочитайте файл2 и выведите любые слова, которые не были видны из файла1:
gawk -v RS='[[:space:]]+' 'NR==FNR {words[$1]=1; next} !($1 in words)' file1 file2
Использует любую последовательность пробелов в качестве разделителя записей, поэтому каждое слово рассматривается как отдельная «строка». Это теперь GNU awk, но это awk по умолчанию на Ubuntu
Хотя критерии удаления не очень ясны, я предполагаю, что части для удаления являются (www\n1_www\n2_www) для всего слова www (исправьте меня, если я ошибаюсь)
Использование (gnu) sed:
sed -zr 's/(\w+)\n1_\1\n2_\1\n//g' ex
Эта командная строка должна выполнить трюк:
while read -r word; do sed -e "s/\<$word\>//g" -e '/^\s*$/d' file2 -i; done < file1
После выполнения вышеуказанной команды выходной файл - file2 - должен выглядеть так:
This
is
my
word
file
Более читаемая версия приведенной выше командной строки:
while read -r word; do \
sed -e "s/\<$word\>//g" -e '/^\s*$/d' file2 -i; \
done < file1
Цикл while читает строку строки за строкой - < file1. Значение каждой строки используется как значение временной созданной переменной, называемой $word - -r word. Эта переменная используется как аргумент внутри команды sed, и она заменяется [s] пустым значением в file2, первым выражением: "s/\<$word\>//g" = s/<source_value>/<replacement_value>/g. Флаг g означает - применить замену ко всем совпадениям. Затем, если в файле есть пустая строка, она удаляется - второе выражение: '/^\s*$/d'.
Нам нужно использовать синтаксис \<...\>, чтобы найти только точные совпадения. Нам нужны двойные кавычки - "..." - для первого выражения, потому что $word - это имя переменной, и мы хотим расширить его как свое значение в команде sed.
Опция -i означает, что изменения будут сделаны в их местах в целевом файле - file2. Если эта опция будет удалена, результат будет передан в stdout, но это не будет иметь смысла. Опция -i.bak неприменима к этому сценарию, потому что целевой файл будет перезаписан много раз, поэтому вы должны создать резервную копию заранее.
Используйте grep с флагом -v (инвертировать).
С помощью расширенного регулярного выражения (-E) вы можете сделать | -сегментированный список шаблонов, которые вы хотите исключить, например pattern1|pattern2|pattern3:
grep -v -E "^[0-9]|world|hello" file
Вы можете использовать grep -f FILE для получения паттернов из файла FILE. В вашем случае я рекомендую несколько дополнительных флагов (см. Объяснение ниже) для следующего окончательного вызова grep:
grep -v -x -F -f file1 -- file2
-f FILE - Получить шаблоны из FILE, по одному на строку. -F. Интерпретировать шаблон как список фиксированных строк, разделенных символами новой строки, любой из которых должен быть сопоставлен. -x - выберите только те совпадения, которые точно соответствуют всей строке. (Вы можете удалить эту опцию, если хотите разрешить частично совпадающие строки.) [F9] - инвертировать смысл соответствия, чтобы выбрать несогласованные строки. Источник: документация GNU grep или, альтернативно, ее страница руководства
Все параметры, используемые выше, задаются POSIX и не требуют расширений GNU.
Вы хотите использовать awk для чтения файла1 и запомнить все его слова. Затем прочитайте файл2 и выведите любые слова, которые не были видны из файла1:
gawk -v RS='[[:space:]]+' 'NR==FNR {words[$1]=1; next} !($1 in words)' file1 file2
Использует любую последовательность пробелов в качестве разделителя записей, поэтому каждое слово рассматривается как отдельная «строка». Это теперь GNU awk, но это awk по умолчанию на Ubuntu
Хотя критерии удаления не очень ясны, я предполагаю, что части для удаления являются (www\n1_www\n2_www) для всего слова www (исправьте меня, если я ошибаюсь)
Использование (gnu) sed:
sed -zr 's/(\w+)\n1_\1\n2_\1\n//g' ex
Эта командная строка должна выполнить трюк:
while read -r word; do sed -e "s/\<$word\>//g" -e '/^\s*$/d' file2 -i; done < file1
После выполнения вышеуказанной команды выходной файл - file2 - должен выглядеть так:
This
is
my
word
file
Более читаемая версия приведенной выше командной строки:
while read -r word; do \
sed -e "s/\<$word\>//g" -e '/^\s*$/d' file2 -i; \
done < file1
Цикл while читает строку строки за строкой - < file1. Значение каждой строки используется как значение временной созданной переменной, называемой $word - -r word. Эта переменная используется как аргумент внутри команды sed, и она заменяется [s] пустым значением в file2, первым выражением: "s/\<$word\>//g" = s/<source_value>/<replacement_value>/g. Флаг g означает - применить замену ко всем совпадениям. Затем, если в файле есть пустая строка, она удаляется - второе выражение: '/^\s*$/d'.
Нам нужно использовать синтаксис \<...\>, чтобы найти только точные совпадения. Нам нужны двойные кавычки - "..." - для первого выражения, потому что $word - это имя переменной, и мы хотим расширить его как свое значение в команде sed.
Опция -i означает, что изменения будут сделаны в их местах в целевом файле - file2. Если эта опция будет удалена, результат будет передан в stdout, но это не будет иметь смысла. Опция -i.bak неприменима к этому сценарию, потому что целевой файл будет перезаписан много раз, поэтому вы должны создать резервную копию заранее.
Используйте grep с флагом -v (инвертировать).
С помощью расширенного регулярного выражения (-E) вы можете сделать | -сегментированный список шаблонов, которые вы хотите исключить, например pattern1|pattern2|pattern3:
grep -v -E "^[0-9]|world|hello" file