Если NR==FNR, необходимо изменить два файла при совпадении

Не используйте цикл вообще. Вместо этого перечислите все файлы и используйте команду, например grepили akw, чтобы отфильтровать файлы между startи stop. printfне будет иметь проблем Argument list too long, так как это bashвстроенный -.

printf '%s\0' /home/me/*/file_*.txt |
grep -cEzf <(seq "$start" "$stop" | sed 's/.*/_&\.txt$/')

Здесь мы предполагаем, что у вас есть версии GNU grep, которые могут обрабатывать нулевые байты. Это важно для безопасной обработки путей. Нулевой байт — единственный символ, который не может быть частью пути, поэтому мы можем использовать его для разделения путей.
Если у вас нет версии GNU, вы можете создать что-то, что разделяет пути символами новой строки, предполагая, что ни один из путей не содержит символ новой строки. Замените \0на \nи снимите флаг -z.

Если вы измените …_*.txtна что-то другое, возможно, вам также придется обновить команду sed.

-2
29.11.2020, 23:06
2 ответа

Ответ на пересмотренный вопрос:

awk 'NR==FNR {$1=""; afile[$2, $3, $4]=$0; next; }
    (($4, $6, $8) in afile){ print $2 afile[$4, $6, $8]; }1' a.txt b.txt

Действительно для старой версии вопроса:

$ awk 'NR==FNR { afile[$2, $3, $4]=1; next; } 
       (($4, $6, $8) in afile){ print $2, $4,$6, $8; }1' a.txt b.txt >c.txt

прочитать a.txtтолько столбцы 2, 3 и 4 в ассоциированный массив с именем afile; затем сравните соответствующие столбцы второго файла b.txtс 4, 6 и 8, если они были видны в массиве, поэтому выведите нужные столбцы из второго файла $1без изменений, а остальные столбцы 4, 6 и 8 как хорошо; иначе выводить по умолчанию 1для несовпадающих строк.

Результатc.txt:

101 A B 580
10 101 E1 A Z1 B Z2 580 Z3
11 104 E2 C Z1 B Z2 581 Z3
107 A B 581
12 107 E3 A Z1 B Z2 581 Z3
14 111 E3 B Z1 S Z2 582 Z3
116 A B 582
15 116 E2 A Z1 B Z2 582 Z3

Но у вас проблемы с кодами:

awk 'NR==FNR{pattern[$0]; next} {if($4" "$6" "$8 in pattern) {print $0; gsub(pattern[$1],$2); print pattern[$0]}}' a.txt b.txt >> c.txt
  1. pattern[$0]:при этом вы добавляете каждую строку целиком в связанный массив шаблона из первого ввода " a.txt";

  2. Затем вы сравниваете столбцы #4, #6 и #8 с $4" "$6" "$8из второго файла b.txtсо строками в этом массиве; они никогда не будут совпадать, так как вы сравниваете целые строки со значениями определенных столбцов, которые не существуют в вашем массиве шаблонов .

  3. поскольку шаг 2 никогда не встречается с вашим внутренним блоком, потому что оператор if также никогда не запускается; и я не буду объяснять, что вы делаете с этим.

2
18.03.2021, 22:46

Сначала мы создаем регулярное выражение из 8 фрагментов/полей с запоминанием четного числа полей. Регулярное выражение основано на gnu sed с расширенным режимом регулярных выражений.

$ re='\S+ (\S+)'
$ for i in 1 2; do re="$re $re"; done
$ sed -En "/\n/{P;d;}
    s/\s+/ /g;s/^ | \$//g
    /(\S+ ){6}/bb
    s/^\S+ //;H;d
    :b;G
    /^$re.*\n(\2 \3 \4 \S+)/{
      s//\1 \5\n&/;P;D
    }
" a.txt b.txt \
| sed -e 'n;H;2h;$!d;g'

Выход:

101 A B 580 D1
107 A B 581 D2
116 A B 582 D3
10 101 E1 A Z1 B Z2 580 Z3
12 107 E3 A Z1 B Z2 581 Z3
15 116 E2 A Z1 B Z2 582 Z3
0
18.03.2021, 22:46

Теги

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