Как добавить отсутствующую строку только путем сравнения 2 столбцов в 2 разных файлах

Используя GNU find, xargsи cp, это будет копировать 10 файлов за раз:

d="destination_directory..."
s="source_directory..."
find "$s" -type f -print0 | xargs -0rn 10 cp -n -t "$d"
0
05.04.2021, 00:35
2 ответа

Может быть, что-то вроде этого?

cat file2 | awk '!(1 in f) {if ((getline l < "-") == 1) split(l, f)} $3!=f[3] {print;next} {print l; delete f}' file1 | column -t

Обратите внимание, что сценарий ожидает file1в качестве аргумента для awk, в то время как ожидает file2в качестве своего стандартного ввода . Я использовал «бесполезное использование cat», чтобы показать это более явно, но, естественно, вместо этого вы можете предоставить его как перенаправление < file2. На самом деле вы можете даже вставить имя файла в сам скрипт, например "file2"вместо "-"на getline, но этот способ немного более гибкий.

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

Только сценарий разбит для удобства чтения,и подробно прокомментирован для объяснения:

# Check if our `real_fields` array is not existent.
# NOTE: we use the `<index> in <array>` construct
# in order to force awk treat `real_fields` name as an
# array (instead of as a scalar as it would by default)
# and build it in an empty state
!(1 in real_fields) {
    # get the next line (if any) from the "real" file
    if ((getline real_line < "-") == 1)
        # split that line in separate fields populating
        # our `real_fields` array
        split(real_line, real_fields)
        # awk split function creates an array with numeric
        # indexes for each field found as per FS separator
}
# if field3 of the current line of the "reference"
# file does not match the current line of the "real" file..
$3!=real_fields[3] {
    # print current line of "reference" file
    print
    # go reading next line of "reference" file thus
    # skipping the final awk pattern
    next
}
# final awk pattern, we get here only if the pattern
# above did not match, i.e. if field3 values from both
# files match
{
    # print current line of "real" file
    print real_line
    # delete our real_fields array, thus triggering
    # the fetching of the next line of "real" file as
    # performed by the first awk pattern
    delete real_fields
}
1
28.04.2021, 22:54

Вам необходимо установить порядок массива, иначе awk -переупорядочит ваши строки.

#!/usr/bin/awk -f

BEGIN {
    PROCINFO["sorted_in"] = "@ind_str_asc"
}
NR==FNR {
    a[i++,$3]=$0
    next
} 
{
    for (c in a) {
        split(c, s, SUBSEP)
        if (s[2] == $3) {
            print $0
            getline
        } else {
            print a[c]
        }
    }
}

./script.awk file1 file2
0
28.04.2021, 22:54

Теги

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