Выберите строки из текстового файла с идентификаторами, указанными в другом файле

Я использую много сортировки grep awk в своей оболочке unix для работы с текстовыми файлами с разделителями разделов с разделителями разделов с разделителями разделов с разделителями-разделителями (размером около 10 М-100 М). В этом отношении оболочка unix является моей таблицей.

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

Имея файл table.csv с id\tfoo\tbar... формата id\tfoo\tbar... и ids.csv со списком идентификаторов, выберите только записи из table.csv с идентификатором, присутствующим в ids.csv .

вид https://stackoverflow.com/questions/13732295/extract-all-lines-from-text-file-based-on-a-given-list-of-ids, но с оболочкой, а не perl.

grep -F очевидно, создает ложные срабатывания, если ids – переменная ширина. join – это утилита, которую я никогда не мог понять. Прежде всего, для этого требуется сортировка по алфавиту (мои файлы обычно сортируются численно), но даже тогда я не могу заставить его работать, не жалуясь на неправильный порядок и пропуская некоторые записи. Поэтому мне это не нравится. grep -f против файла с ^id\t -s очень медленный, когда число идентификаторов велико. awk громоздкий.

Есть ли хорошие решения для этого? Какие-либо конкретные инструменты для разделенных табуляцией файлов? Также будут приветствоваться дополнительные функции.

UPD: Исправлена sort -> join

  • Удалить конкретный столбец, если он существует в файле CSV
  • Сравните файл с столбцом другого файла
  • Как объявить данные R CSV как числовые?
  • Преобразовать файл .xlsx (MS Excel) в .csv в командной строке с полями, разделенными точкой с запятой
  • Координаты данных с awk
  • Преобразование таблицы csv в HTML
  • Как я могу превратить уродливый вывод в красивую и полезную информацию?
  • как преобразовать несколько txt в CSV с данными поля, разделенными пустыми линиями
  • 4 Solutions collect form web for “Выберите строки из текстового файла с идентификаторами, указанными в другом файле”

    Я предполагаю, что вы имели в виду grep -f не grep -F но вам действительно нужна комбинация обоих и -w :

     grep -Fwf table.csv ids.csv 

    Причина, по которой вы получали ложные срабатывания, (я думаю, вы не объяснили), потому что если идентификатор может содержаться в другом, то оба будут напечатаны. -w устраняет эту проблему, и -F гарантирует, что ваши шаблоны рассматриваются как строки, а не регулярные выражения. От man grep :

      -F, --fixed-strings Interpret PATTERN as a list of fixed strings, separated by newlines, any of which is to be matched. (-F is specified by POSIX.) -w, --word-regexp Select only those lines containing matches that form whole words. The test is that the matching substring must either be at the beginning of the line, or preceded by a non-word constituent character. Similarly, it must be either at the end of the line or followed by a non-word constituent character. Word-constituent characters are letters, digits, and the underscore. -f FILE, --file=FILE Obtain patterns from FILE, one per line. The empty file contains zero patterns, and therefore matches nothing. (-f is specified by POSIX.) 

    Если ваши ложные срабатывания связаны с тем, что идентификатор может присутствовать в поле, отличном от идентификатора, вместо этого прокрутите свой файл:

     while read pat; do grep -w "^$pat" table.csv; done < ids.csv 

    или, быстрее:

     xargs -I {} grep "^{}" table.csv < ids.csv 

    Лично я сделал бы это в perl хотя:

     perl -lane 'BEGIN{open(A,"ids.csv"); while(<A>){chomp; $k{$_}++}} print $_ if defined($k{$F[0]}); ' table.csv в perl -lane 'BEGIN{open(A,"ids.csv"); while(<A>){chomp; $k{$_}++}} print $_ if defined($k{$F[0]}); ' table.csv 

    Утилита join – это то, что вы хотите. Это требует, чтобы входные файлы были лексически отсортированы.

    Предполагая, что ваша оболочка bash или ksh:

     join -t $'\t' <(sort ids.csv) <(sort table.csv) 

    Обычное awk-решение не требует сортировки.

     awk -F '\t' 'NR==FNR {id[$1]; next} $1 in id' ids.csv table.csv 

    Ответы на этот вопрос SO помогли мне обойти ничтожество с присоединением. По сути, когда вы сортируете файл, готовый отправить его, чтобы присоединиться, вам нужно убедиться, что вы сортируете на основе столбца, к которому вы присоединяетесь. Итак, если это первый, вам нужно сказать ему, что символ разделителя в файле, и что вы хотите, чтобы он сортировался в первом поле (и только в первом поле). В противном случае, если первое поле имеет переменную ширину (например), ваши разделители и, возможно, другие поля могут начать влиять на порядок сортировки.

    Итак, используйте опцию -t для сортировки, чтобы указать разделительный символ, и используйте параметр -k, чтобы указать поле (помня, что вам нужно поле начала и окончания – даже если это то же самое – или он будет сортировать из этого символа до конца строки).

    Итак, для файла с разделителями табуляции, как в этом вопросе, должно работать следующее (с благодарностью за ответ Гленна за структуру):

    join -t$'\t' <(sort -d ids.csv) <(sort -d -t$'\t' -k1,1 table.csv) > output.csv

    (Для справки, флаг -d означает сортировку слова. Вы также можете использовать флаг -b, чтобы игнорировать ведущие пробелы, см. man sort and man join ).

    В качестве более общего примера предположим, что вы соединяете два разделенных запятыми файлов – input1.csv на третьем столбце и input2.csv на четвертом. Вы можете использовать

    join -t, -1 3 -2 4 <(sort -d -t, -k3,3 input2.csv) <(sort -d -t, -k4,4 input2.csv) > output.csv

    Здесь параметры -1 и -2 определяют, какие поля должны объединяться в первом и втором входных файлах соответственно.

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

     ruby -pe 'File.open("id.csv").each { |i| puts i if i =~ /\$\_/ }' table.csv 
    Interesting Posts

    Все возможные перестановки слов в разных файлах попарно

    Отправить сетевой трафик через виртуальную машину Windows на том же хосте, чтобы использовать корпоративный vpn?

    Удаленный мониторинг сетевого трафика серверов

    Каков эффект разрешения файлов на системном уровне?

    Fedora Core 4 не получит адрес IPV4

    Существует ли привязка ключа к переключению на «последнее» рабочее пространство в mint 17.2?

    Должно ли приостановленное приложение в фоновом режиме (ctrl + z) запускаться или оно должно прекратиться?

    Разблокируйте Android зашифрованный файл DISK IMAGE FILE на SD-карте на настольном Linux

    Как установить пакеты в пользовательское местоположение в centos6

    Linux общий FTP: нельзя удалять один файл

    Замените все буквы словом «*» после определенного слова в текстовом файле

    Значок панели Thunderbird для уведомлений по почте

    Регулярное выражение для каждого слова, содержащего & с $ … $

    Pulseaudio и Pavucontrol очень неустойчивы

    Каков наилучший способ добавления постоянного маршрута?

    Linux и Unix - лучшая ОС в мире.