简体   繁体   English

如何使用 sed 或 awk 将 file1 的一部分替换为 file2 的一部分,部分由行和列描述

[英]How to replace a portion of file1 by a portion of file2 uing sed or awk, portion delineated by row and column no

I have two files, say file1 and file2 and they are in the following format我有两个文件,比如 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

What I want for the updated file1 is the following:我想要更新的 file1 如下:

first row
XX  5.5  6.6  9.8
YY  5.4  5.6  7.8

I know I can replace lines if the string in file1 matches a string I provide by using this command我知道如果 file1 中的字符串与我使用此命令提供的字符串匹配,我可以替换行

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

However for this case, it should be much easier to replace the values using their row and column numbers.但是对于这种情况,使用它们的行号和列号替换值应该更容易。 May I know how to go about doing this?我可以知道如何 go 关于这样做吗?

The actual files: File1:实际文件: File1:

&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

This is file2:这是文件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

I'm trying to replace the ATOMIC_POSITIONS portion of file1 (from row 37 column 2 to row 44 column4) with the bottom chunk of file2 (from row 10 column 1 to row 17 column 3).我正在尝试用 file2 的底部块(从第 10 行第 1 行到第 17 行第 3 列)替换 file1 的 ATOMIC_POSITIONS 部分(从第 37 行第 2 列到第 44 行第 4 列)。

So the bottom of file1 should be something like this:所以 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

EDIT2: Since OP mentioned actual samples now, which are different from previous, so adding this now. EDIT2:由于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

If happy with above's result then append > temp && mv temp Input_file1 to above.如果对上面的结果感到满意,那么 append > temp && mv temp Input_file1到上面。



EDIT: Since OP clarified question more got to know that row number from source(Input_file2) could be different from target(Input_file1), so let's say we have following Input_files.编辑:由于 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

Where variables source_row is for Input_file from where we need to pickup the values and variable target_row for target Input_file where we need to place the rows.其中变量source_row用于 Input_file,我们需要从中获取值,变量target_row用于目标 Input_file,我们需要在其中放置行。

To save output into Input_file1 append at last of above command > temp && mv temp Input_file1将 output 保存到 Input_file1 append 在上述命令的最后> temp && mv temp Input_file1



In case you want to replace rows in Input_file1 by row number then try following.如果您想用行号替换 Input_file1 中的行,请尝试以下操作。

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

Output will be as follows. Output 如下。

XX b1 b2 b3
YY b4 b5 b6

Split file 1 into a header file and a footer file.将文件 1 拆分为 header 文件和页脚文件。

header file includes all the strings before row 37 (exclusive) and the footer includes rows after 45 (inclusive). header 文件包含第 37 行(不含)之前的所有字符串,页脚包含第 45 行(含)之后的行。 Then the code looks like the following:然后代码如下所示:

cp file1.header file1

awk '\
NR == 10 || NR == 11 { print "Nb " $1 " " $2 " " $3 }\
NR >= 12 && NR <= 15 { print "I  " $1 " " $2 " " $3 }\
NR == 16 || NR == 17 { print "O  " $1 " " $2 " " $3 }\
' file2>> file1

cat ../file1.footer >> file1 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 用sed代替一部分字符串 - replace with sed a portion of a string sed用file1中的file3内容替换file2内容 - sed replace file2 content with file3 content in file1 如果它们与 file2 中第 1 列中的列表匹配,我如何使用 awk 仅打印 file1 给定行中的值? - How can I use awk to only print values in a given row of file1 if they match with a list in column 1 in file2? awk查找并在匹配时将变量file2替换为file1 - awk find and replace variable file2 into file1 when matched 如果file1的第一列与file2中的任何字符串匹配,则将其替换为file1的第二列 - If the first column of file1 matches any string in file2, then replace it with the second column of file1 需要用file1的第二列替换与file1的第一列匹配的file2中的字符串 - Need to replace string in file2 that matches first column of file1 with second column of file1 如何在Shell脚本中提取文件的一部分 - How to extract a portion of a file in shell script 如何仅在文件的一部分上使用readarray / mapfile? - How to use readarray / mapfile on only a portion of a file? 如何提取.gz文件的一部分(不是开头)? - How to extract a portion (not beginning) of .gz file? Awk 获取file1列并检查file2的column1,如果匹配则打印相应的值 - Awk to get file1 column and check column1 of file2,if matches then print the corresponding value
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM