Замените нечетные строки в одном текстовом файле соответствующими нечетными строками в другом текстовом файле с помощью sed/awk/etc

while read -r seed name; do
    sed -e "s/^seed.*/seed $seed/" \
        -e "s/^output.*/output $name/" template.txt >"${name%.*}-$seed.conf"
done <file.in

Будет прочитан файл с именем file.in. Формат этого файла должен быть

00000 filename.ext

(начальное значение в первом столбце, пробел и имя файла)

Команда sedвозьмет шаблон из template.txt, файла, отформатированного как в вопросе, и сгенерирует новые файлы.

Новые файлы будут иметь такие имена, какfilename-00000.conf(с использованием имени файла без расширения имени файла и исходным кодом из файла file.in).

Выражения sedпросто ищут строки в template.txt, которые начинаются с seedили output, и вставляют соответствующие значения.

0
20.07.2019, 18:44
5 ответов
$ awk 'NR==FNR{a[NR]=$0; next} {print (FNR%2 ? $0 : a[FNR])}' file1 file2
>name.A
GGG
>name.B
AAA
>name.C
TTT
>name.D
CCC
>name.E
CAT

Помимо того, что это более лаконично (и работает :-)), приведенный выше подход более эффективен, чем ваш подход, потому что:

  1. Он не присваивается $0 и поэтому не заставляет awk заново разбивать запись на поля
  2. Он не проверяет второе условие(1)для каждой строки перед тем, как решить, печатать или нет.

Также -не используйте перенаправление ввода для открытия файлов для awk, так как оно не работает для нескольких файлов (, как вы выяснили ), и лишает вас возможности проверить ИМЯ ФАЙЛА.

2
28.01.2020, 02:39

Ваша awk-команда в основном верна -она будет работать, если вы удалите посторонние перенаправления и поменяете порядок файлов:

$ awk 'FNR==NR {data[FNR]=$0; next} (FNR%2==1){$0=data[FNR]}1' File2 File1
>name.A
GGG  
>name.B
AAA  
>name.C
TTT  
>name.D
CCC  
>name.E
CAT 

В качестве альтернативы, с GNU sed и оболочкой, поддерживающей подстановку процессов:

$ sed -e '2~2{R /dev/stdin' -e 'd}' File2 < <(sed '1~2d' File1)
>name.A
GGG  
>name.B
AAA  
>name.C
TTT  
>name.D
CCC  
>name.E
CAT 

Пояснение:

  • sed '1~2d' File1удалить нечетные строки из файла 1

  • < <(...)передать результаты через стандартный ввод

  • sed -e '2~2{R /dev/stdin' -e 'd}' File2считывать по одной строке со стандартного ввода и ставить ее в очередь для вставки после следующей четной строки File2; затем удалите четную строку

1
28.01.2020, 02:39

Попробуйте так, это сложно, но работает. Возможно, есть более простое решение.

  • Первые отдельные нечетные и четные линии:

    awk '{print>"файл1 -"NR%2}" файл1 awk '{print>"файл2 -"NR%2}" файл2

Это создаст file1-0, file1-1, file2-0, file2-1В моем случае и в вашем примере файл1 -0 содержит данные, которые вам нужны из файла1, а файл2 -1 содержит данные, которые вам нужны из файла2, проверьте вывод этих файлов ниже

[mtodoric@bulletproof test]$ cat file1-0
GCCAAACAGCTAGCTTGA
GCCAAACAGCTAGCTTGATTAATAA
GCCAAACAGCTAGCTTGATTAATAATATAA
GCCAACCAGCTAGCTTAA
GCTAACCAGCTAGCTTAA
GCTGACTAGCTAGCCAACATATTT
GCCCAACAGCTAGCCCACTCA
GCCAACCAGCTAGCTTAAT
GCCAACCAGCTAGCTTAATT

[mtodoric@bulletproof test]$ cat file2-1
Siphateles.boraxobius_complete-mitochondrion_harney-county-or.fasta
Siphateles.boraxobius_complete-mitochondrion_harney-county-or.fasta
Siphateles.alvordensis_complete-mitochondrion_harney-county-or.fasta
Rhinichthys.evermanni_complete-mitochondrion_douglas-county-or.fasta
Oregonichthys.kalawatseti_complete-mitochondrion_linn-county-or.fasta
Oncorhynchus.mykiss.irideus_complete-mitochondrion_douglas-county-or.fasta
Cottus.perplexus_complete-mitochondrion_douglas-county-or.fasta
Oncorhynchus.mykiss.irideus_complete-mitochondrion_douglas-county-or.fasta
Cottus.perplexus_complete-mitochondrion_douglas-county-or.fasta
  • Теперь сделайте «oneliner», который объединит данные.

    РБ=1; при чтении строки; выполнить эхо $line >> final.txt; sed -n ${RB}p file1 -0 >> final.txt; RB=$ ((${RB}+1 )); сделано < файл2 -1

Это в основном будет читаться из файла2 -1 (, так как в этом файле была первая строка из вашего примера вывода ), повторите каждую строку в другой файл (final.txt ), но также, благодаря переменной RB получит этот номер строки из другого файла и напечатает стандартный вывод в final.txt, а также увеличит значение RB, чтобы он мог увеличивать строку в следующем цикле.

Замените имена file2 -1 и file1 -0 в "one liner", чтобы они соответствовали вашим данным.

Надеюсь, это поможет.

1
28.01.2020, 02:39

Пробовал с помощью команды sed, все работает нормально

for ((i=2;i<=10;i++));do j=`sed -n ''$i'p' f1`; k=`echo $j|sed -r "s/\s+//g"`;sed -i ""$i"s/.*/"$k"/g" f2;i=$(($i+1)); done

выход

>name.A
GGG
>name.B
AAA
>name.C
TTT
>name.D
CCC
>name.E
CAT
1
28.01.2020, 02:39

Вы можете сделать свой pbm следующим образом, сначала вызвав утилиту paste, чтобы расположить строки в порядке, разделенном TAB, а затем вызвать редактор sed, чтобы выполнить операцию для получения желаемых выходных данных:

$ paste File1 File2  | sed -ne '
    s/>.*\t//p
    s/\t.*//p
 '

Выход

>name.A
GGG  
>name.B
AAA  
>name.C
TTT  
>name.D
CCC  
>name.E
CAT 

Примечание. :Posix sed не распознает \tуправляющую последовательность вместо символа табуляции. Я просто использовал его, чтобы выделить невидимый символ otw. Таким образом, вы помещаете буквальную вкладку вместо \t.

С утилитой Perlэто один -вкладыш:

$ perl -pe '$_=($_,$,.<STDIN>)[$.%2]' File1 < File2
1
28.01.2020, 02:39

Теги

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