Как заменить часть file1 частью file2 с помощью sed или awk, часть обозначена строкой и столбцом no - PullRequest
0 голосов
/ 16 октября 2019

У меня есть два файла, скажем, file1 и file2, и они имеют следующий формат

file1:
many rows
36th rows
XX  1.1  1.2  9.9
YY  2.5  3.6  3.8

file2
several rows
9th row
5.5  6.6  9.8  T  T  T
5.4  5.6  7.8  T  T  T

Что я хочу для обновленного файла1, это следующее:

first row
XX  5.5  6.6  9.8
YY  5.4  5.6  7.8

Я знаюЯ могу заменить строки, если строка в file1 совпадает со строкой, которую я предоставляю с помощью этой команды

sed -i "s/1.1  1.2  9.9/5.5  6.6  9.8/" file1

Однако в этом случае будет гораздо проще заменить значения, используя их номера строк и столбцов. Могу ли я узнать, как это сделать?

Фактические файлы: Файл1:

&control
     calculation='scf'
     restart_mode='from_scratch'
     prefix='prefix1'
     pseudo_dir = '.'
     nstep = 2000,
     etot_conv_thr = 1.0E-6 ,
     forc_conv_thr = 1.0D-4,
     outdir = prefix1

/
 &system
    ibrav=0,
    nat=8,
    ntyp=3,
    ecutwfc = 60.0,   
    ecutrho = 600,
/
&electrons
    electron_maxstep = 250
    mixing_beta     = 0.1
    conv_thr        = 1.0d-10
/

CELL_PARAMETERS (angstrom)
     3.9746359870249388    0.0000000000000000    0.0000000000000000
     0.0000000000000000    7.5980663633997150    0.0000000000000000
     0.0000000000000000    0.0000000000000000   24.1776735510378913


ATOMIC_SPECIES
  I 126.90447d0 I.pbe-n-kjpaw_psl.1.0.0.UPF
  Nb 92.906400d0 Nb.pbe-spn-kjpaw_psl.1.0.0.UPF
  O 15.999400d0 O.pbe-n-kjpaw_psl.1.0.0.UPF

ATOMIC_POSITIONS {crystal}
Nb  0.7500000000000000  0.3084626380344986  0.5000000000000000
Nb  0.7500000000000000  0.8915373619655043  0.5000000000000000
I   0.7500000000000000  0.6000000000000014  0.5781487300676179
I   0.7500000000000000  0.1000000000000014  0.5953056146454921
I   0.7500000000000000  0.1000000000000014  0.4046943853545079
I   0.7500000000000000  0.6000000000000014  0.4218512699323820
O   0.2500000000000000  0.3124817357885405  0.5000000000000000
O   0.2500000000000000  0.8875182642114551  0.5000000000000000
K_POINTS {automatic}
12 6 1 0 0 0

Это файл2:

Nb I O                                  
   1.00000000000000     
     3.9746359870249388    0.0000000000000000    0.0000000000000000
     0.0000000000000000    7.5980663633997150    0.0000000000000000
     0.0000000000000000    0.0000000000000000   24.1776735510378913
   Nb   I    O 
     2     4     2
Selective dynamics
Direct
  0.11  0.21  0.31   F   F   F
  0.12  0.22  0.32   F   F   F
  0.13  0.23  0.33   T   T   T
  0.14  0.24  0.34   T   T   T
  0.15  0.25  0.35   T   T   T
  0.16  0.26  0.36   T   T   T
  0.17  0.27  0.37   F   T   T
  0.18  0.28  0.38   F   T   T

Я пытаюсь заменитьчасть ATOMIC_POSITIONS в файле1 (из строки 37 столбца 2 в строку 44 столбца 4) с нижним фрагментом файла file2 (из строки 10 столбца 1 в строку 17 столбца 3).

Таким образом, нижняя часть файла file1 должна выглядеть примерно так:это:

ATOMIC_POSITIONS {crystal}
Nb        0.11  0.21  0.31
Nb        0.12  0.22  0.32
I         0.13  0.23  0.33
I         0.14  0.24  0.34
I         0.15  0.25  0.35
I         0.16  0.26  0.36
O         0.17  0.27  0.37
O         0.18  0.28  0.38

K_POINTS {automatic}
12 6 1 0 0 0

1 Ответ

2 голосов
/ 16 октября 2019

РЕДАКТИРОВАТЬ 2: Так как OP упомянул фактические образцы сейчас, которые отличаются от предыдущих, поэтому добавьте это сейчас.

awk '
FNR==NR{
  if(!NF){
     flag=""
  }
  if($0=="Direct"){
     flag=1
  }
  if(flag){
     array[++count]=$1 OFS $2 OFS $3
  }
  next
}
/ATOMIC_POSITIONS {crystal}/{
  found=1
}
!NF{
  found=count1=""
}
found{
  print $1"\t"array[++count1]
  next
}
1
'  Input_file2 Input_file1

Если доволен результатом выше, тодобавьте > temp && mv temp Input_file1 к вышеуказанному.



РЕДАКТИРОВАТЬ: Поскольку уточненный вопрос OP больше узнать, номер строки из источника (Input_file2) можетбудет отличаться от цели (Input_file1), поэтому предположим, что у нас есть следующие Input_files.

awk -v source_row="10,11,12,13,14,15,16,17" -v target_row="37,38,39,40,41,42,43,44" '
BEGIN{
  split(source_row,array_source,",")
  num=split(target_row,array_target,",")
  for(i=1;i<=num;i++){
     replace_array[array_target[i]]
  }
}
FNR==NR{
  a[FNR]=$1 OFS $2 OFS $3
  next
}
(FNR in replace_array){
  print $1"\t"a[array_source[++count]]
  next
}
1
'  Input_file2   Input_file1

Где переменные source_row для Input_file, откуда нам нужно получить значения и переменную target_row для целевого Input_file, гденам нужно разместить строки.

Чтобы сохранить вывод в Input_file1, добавьте последнюю из вышеприведенных команд > temp && mv temp Input_file1



В случае, если вы хотите заменить строки в Input_file1 на строкузатем попробуйте следующий.

awk 'FNR==NR{a[FNR]=$1 OFS $2 OFS $3;next} {print $1,a[FNR]}' Input_file2  Input_file1

Вывод будет следующим.

XX b1 b2 b3
YY b4 b5 b6
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...