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

cat file1.txt

aa
bb
cc

cat file2.txt

site.com
site2.com
site3.com

Ожидаемый результат будет выглядеть так:

aa.site.com
aa.site2.com
aa.site3.com
bb.site.com
bb.site2.com
bb.site3.com
cc.site.com
cc.site2.com
cc.site3.com

2 ответа2

1

Самое простое, что вы можете использовать paste для объединения строк ваших файлов. Его опция -d позволяет вам выбрать разделитель (здесь, a .).

Трудная часть здесь - декартово произведение. Заимствуя из этого ответа на SO, мы можем придумать такую команду:

paste -d '.' \
  <(sed -n "$(yes 'p;' | head -n $(wc -l <file2.txt) )" file1.txt) \
  <(cat $(yes 'file2.txt' | head -n $(wc -l <file1.txt)))

Где мы:

  • Объедините yes и head для создания сценария sed который будет печатать каждую строку file1.txt количество раз, равное количеству строк в file2.txt ;
  • Объедините yes и head чтобы cat print file2.txt равнялся числу строк в file1.txt ;
  • Используйте paste чтобы объединить каждую пару строк, напечатанных двумя подстановками процесса (<(...)), разделенными символом . ,

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

while ... do ... done <file | cat -

Для удобства вы можете определить функцию и сделать ее доступной для вашей среды (например, определив ее в вашем .bashrc если вы используете bash).
Например, здесь используются циклы, чтобы минимизировать потребность во внешних инструментах:

function cart_prod () {
  while IFS= read -r line1; do
    while IFS= read -r line2; do
      printf '%s.%s\n' "$line1" "$line2"
    done <"$2"
  done <"$1"
}

Пример использования:

$ cart_prod file1.txt file2.txt | sort -r
cc.site.com
cc.site3.com
cc.site2.com
bb.site.com
bb.site3.com
bb.site2.com
aa.site.com
aa.site3.com
aa.site2.com
1

С bash:

while IFS= read -r line1; do while IFS= read -r line2; do echo "$line1.$line2"; done <file2.txt; done <file1.txt

или же

join -j 64 <(sort file1.txt) <(sort file2.txt) -o 1.1,2.1 | sed 's/ /./'

Выход:

aa.site.com
aa.site2.com
aa.site3.com
bb.site.com
bb.site2.com
bb.site3.com
cc.site.com
cc.site2.com
cc.site3.com

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .