Сопоставление между двумя файлами

Всякий раз, когда у меня возникала эта ошибка, это было связано с несоответствием версий usbip -utils между клиентом и сервером. Проверьте оба, выполнив usbip version, который должен вернуть что-то вроде строкusbip (usbip-utils 2.0)

1
12.05.2021, 15:01
6 ответов

Сawk:

awk '{printf "update_job: %s\n", $1 ; getline < "value.txt"; printf "max_run_alarm: %s\n\n", $1 }' jobname.txt

Первая команда printfпечатает строку из первого файла jobname.txt. Затем команда getlineберет строку из файла value.txt. Затем команда printfпечатает эту строку.

см. http://awk.freeshell.org/AllAboutGetline, когда и как использовать getline.

2
28.07.2021, 11:32

С paste+awk:

$ paste -d'\n' jobname.txt value.txt \
  |awk '{ print (NR%2?"update_job:":"max_run_alarm:", $0) }'

В основном с помощью команды paste, как следует из ее названия, мы вставляем оба файла построчно из каждого, но добавляем один символ \newline между каждой строкой, затем -обрабатываем предыдущий вывод с помощью awkи мы добавляем нужный "текст" для строк, номер строки которых равен модулю 2 (строк с четными номерами строк; например номера строк 2, 4, 6,...; NRсодержит номер строки, которую awk считывает для обработки )мы добавляем текст «update _job :» или для нечетных номеров строк мы добавляем текст "max _run _alarm:", затем напечатайте саму строку $0.

Всего лишьawk:

awk 'NR==FNR{ 
    getline val<ARGV[2]; print "update_job:", $0 ORS "max_run_alarm:", val; next
}
{ exit }' jobname.txt value.txt

Здесь мы обрабатываем по-другому, выше мы сказали, что NR — это номер строки, здесь вы видите FNR; NR и FNR всегда имеют одно и то же значение (, т. е. они оба содержат номер строки ), но NR продолжает увеличиваться для всех строк всех входных файлов, в то время как FNR сбрасывается обратно в 1, как только считывается следующий входной файл. (, если есть ), поэтому, говоря NR==FNR, мы гарантируем, что следующий блок кода будет выполняться только для первого входного файла.

затем мы вызываем "getlineв переменную из файла ", чтобы прочитать одну строку из второго аргумента, который мы передали в качестве входных данных (здесьARGV[2]вернутьvalue.txt)и сохранить его в valпеременная; то остальное просто печатает вещи. ORS печатает разрыв строки между каждым.

или, может быть, вы предпочитаете этот (, но мне не нравится жесткое -кодирование имя_файла):

awk '{ 
    getline val<"value.txt"; print "update_job:", $0 ORS "max_run_alarm:", val
}' jobname.txt
7
28.07.2021, 11:32

В bash самый простой способ сделать это — прочитать оба файла в два разных массива, а затем выполнить итерацию от 1до длины одного из массивов.

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

Например, использование массивов jи vдля заданий и значений:

$ cat mapping.sh 
#!/bin/bash

mapfile -t -O 1 j < jobname.txt
mapfile -t -O 1 v < values.txt

for i in $(seq 1 "${#j[@]}") ; do
  printf "update_job: %s\n" "${j[$i]}"
  printf "max_run_alarm: %s\n\n" "${v[$i]}"
done

Пример вывода:

$ chmod +x./mapping.sh
$./mapping.sh 
update_job: job1
max_run_alarm: 10

update_job: job2
max_run_alarm: 20

Вawk:

$ cat mapping.awk
#!/usr/bin/awk -f

FNR==NR { # reading first file
  j[i++] = $0
  next;
}

{ # reading second file
  v[n++] = $0
}

END {
  for (i in j) {
      printf "update_job: %s\n", j[i]
      printf "max_run_alarm: %s\n\n", v[i]
  }
}

Выход:

$ chmod +x./mapping.awk
$./mapping.awk jobname.txt values.txt 
update_job: job1
max_run_alarm: 10

update_job: job2
max_run_alarm: 20
2
28.07.2021, 11:32
$ paste jobname.txt value.txt |
    awk '{printf "update_job: %s\nmax_run_alarm: %s\n\n", $1, $2}'
update_job: job1
max_run_alarm: 10

update_job: job2
max_run_alarm: 20

или все в awk:

$ awk '
    NR==FNR { jobs[NR]=$1; next }
    { printf "update_job: %s\nmax_run_alarm: %s\n\n", jobs[FNR], $1 }
' jobname.txt value.txt
update_job: job1
max_run_alarm: 10

update_job: job2
max_run_alarm: 20

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

3
28.07.2021, 11:32
 co=`awk 'END{print NR}'  jobname.txt`

for ((i=1;i<=$co;i++)); do awk -v i="$i" 'NR==i{print "update_job: "$1}' jobname.txt; awk -v i="$i" 'NR==i{print "max_run_alarm: "$1}' value.txt;echo -e "\n"; done

выход

update_job: job1
max_run_alarm: 10


update_job: job2
max_run_alarm: 20
2
28.07.2021, 11:32

Используя GNU sed мы можем сделать это, запустив два sed параллельно и вставив вывод одного в пространство шаблонов другого с помощью команды R

$ < values.txt \
  sed -e 's/^/max_run_alarm: /' \
| sed -e '
    s/^/\nupdate_job: /
    1s/.//; R/dev/stdin
' keys.txt

Еще один способ — использовать python3 и заархивировать итераторы двух файловых дескрипторов:

$ python3 -c 'import sys
keys,values = sys.argv[1:]
p,q = "update_job:","max_run_alarm:"
with open(keys) as k, open(values) as v:
  for a,b in zip(k,v):
    print(p,a+q,b,sep=" ")
' keys.txt values.txt

Используя perl мы можем поместить один файл в стандартный ввод, другой в командной строке:

$ perl -ne '
  print for(
    "update_job: $_",
    "max_run_alarm: ".<STDIN>."\n");
' keys.txt < values.txt

Выход:

update_job: job1
max_run_alarm: 10

update_job: job2
max_run_alarm: 20
0
28.07.2021, 11:32

Теги

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