Чтение только части шаблона из файла - PullRequest
0 голосов
/ 15 мая 2018

У меня есть список строк в файле.Я хочу выяснить, какие из этих строк при добавлении к определенному префиксу не существуют в другом файле.

Поэтому, если список строк похож на этот

foo
bar
baz
qux

и целевой файлэто

prefix-foo
prefix-barnotreally
prefix-baz

вывод команды должен быть

bar
qux

Мне известен флаг -f grep, но, насколько я знаю, он неразрешить пользователю использовать строки в файле как только часть шаблона

Ответы [ 5 ]

0 голосов
/ 15 мая 2018

С помощью awk

awk 'NR==FNR{a=a " " $0;next} ! match(a,"\\<"$0"\\>")' targetfile liststrings

Получить весь целевой файл в строке a и не печатать строку списков строк, найденных в строке a

0 голосов
/ 15 мая 2018

Другой вариант - использовать стандартный инструмент Unix join:

join -t- -1 1 -2 2 -v 1 <(sort file1) <(sort -t- -k 2 file2)

Команда объединяет две таблицы в некотором поле соединения. Это требует, чтобы два файла были отсортированы по полю соединения, поэтому нам нужны две команды сортировки. Мы также могли бы сделать это немного более читабельным, используя временные файлы:

sort file1 > file1.sorted
sort -t- -k 2 file2 > file2.sorted
join -t- -1 1 -2 2 -v 1 file1.sorted file2.sorted

Первая команда sort просто сортирует строки файла. Вторая команда сортировки сортируется по второму полю (-k 2), используя тире в качестве разделителя полей (-t-).

Команда join также указывает - в качестве разделителя полей (-t-) и выбирает первый столбец в первом файле в качестве ключа объединения (-1 1), а второй столбец во втором файле ( -2 2). Вывод ограничен неперемещаемыми строками из первого файла (-v 1).

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

0 голосов
/ 15 мая 2018

Вы можете использовать awk, если вы знакомы с ним.Вот пример:

$ cat test.data
prefix-foo
prefix-barnotreally
prefix-baz
$ cat test.awk
BEGIN {
    split("foo bar baz qux", a);
}

/^prefix-*/ {
    gsub("^prefix-", "");
    for (i in a)
        if ($0 == a[i])
            found[$0] = ""
}

END {
    for (i in a)
        if (!(a[i] in found))
            print a[i]
}
$ awk -f test.awk test.data
bar
qux
0 голосов
/ 15 мая 2018

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

#! /bin/bash

if [ $# -ne 2 ]; then
    echo "Usage: $0 <file1> <file2>"
    exit 1
fi

fStrings=$1
file=$2

while read string; do
    cat $file | grep -qw $string
    if [ $? -ne 0 ]; then
        echo $string
    fi
done < $fStrings
0 голосов
/ 15 мая 2018

Вы можете использовать подстановку процесса для извлечения части строки из второго файла, который будет передан параметру -f grep:

grep -vxFf <(cut -f2- -d- file2) file1
  • -v - обратный поиск; найти строки, которые не соответствуют
  • -x - соответствует всей строке
  • -F - искать строки, а не регулярные выражения
  • <(cut -f2- -d- file2) - извлечь строки из целевого файла, оставив после себя префикс
...