Заменить определенные строки файла значениями другого файла

locateне "в реальном времени" :он сканирует файловую систему и запоминает файлы и местоположения в своей внутренней базе данных. Вот что происходит с вами здесь, когда вы бежите:

/usr/bin/youtube-dl

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

slocate -u

все подробности:https://ss64.com/bash/locate.html

0
23.03.2021, 21:35
3 ответа
awk '
    FNR == NR { data[++n] = $0; next }
    {
        data[2] = $1; data[6] = $2; data[7] = $3;
        outname = sprintf("out%d", FNR)  # or: outname = "out" FNR
        for (i = 1; i <= n; ++i)
            print data[i] >outname
        close(outname)
    }' file1 file2

Сначала читается file1, затем file2.

При чтенииfile1(блока FNR == NR)единственное, что делает код awk— это сохраняет каждую строку в массиве data.

При чтении file2код берет каждое из трех полей в строке этого файла и присваивает им индексы в data, соответствующие строкам, которые вы хотите изменить в file1.

Строки, хранящиеся в data, затем печатаются в имя файла, составленное путем взятия номера текущей строки в file2и добавления к нему строки out.

close(outname)действительно необходим только в том случае, если вы используете awk, который не является GNU awk, и вы записываете в большее количество файлов, чем ограничение на дескрипторы открытых файлов (больше, чем ulimit -n] возвращает минус три для стандартных потоков ).

Тестирование:

$ tree
.
|-- file1
`-- file2

0 directory, 2 files
$ awk '
    FNR == NR { data[++n] = $0; next }
    {
        data[2] = $1; data[6] = $2; data[7] = $3;
        outname = sprintf("out%d", FNR)
        for (i = 1; i <= n; ++i)
            print data[i] >outname
        close(outname)
    }' file1 file2
$ tree
.
|-- file1
|-- file2
|-- out1
|-- out2
`-- out3

0 directory, 5 files
$ paste out[123]
w       w       w
1       6       5
y       y       y
G       G       G
7       7       7
1       6       6
1       7       5
2
28.04.2021, 22:57
$ cat tst.awk
BEGIN {
    split("2 6 7",tmp)
    for (fldNr in tmp) {
        map[tmp[fldNr]] = fldNr
    }
}
NR==FNR {
    rows[++numRows] = $i
    next
}
{
    out = "out" FNR
    for (rowNr=1; rowNr<=numRows; rowNr++) {
        print (rowNr in map ? $(map[rowNr]) : rows[rowNr]) > out
    }
    close(out)
}

$ awk -f tst.awk file1 file2

$ head out?
==> out1 <==
w
1
y
G
7
1
1

==> out2 <==
w
6
y
G
7
6
7

==> out3 <==
w
5
y
G
7
6
5
1
28.04.2021, 22:57

Используя GNU sed мы получаем выходные данные в файлах _0/1/2 для каждой строки файла2.

tmpf=$(mktemp) i=0
while read -ra a <&3
do
   printf '%s\n' "${a[@]}" > "$tmpf"
   sed -ne "
      $(printf '%dba\n' 2 6 7)
      p;d;:a
      R $tmpf
   " file1 > "out_$i"
    (( i++ ))
done 3< file2
  • чтение файла2 в цикле while и преобразование полей из пробелов в разделители новой строки и сохранение во временном файле.
  • заставить sed вызывать команду R для строк с номерами 2, 6 и 7 файла file1, чтобы получить желаемый результат.
1
28.04.2021, 22:57

Теги

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