Text-Processing

使用另一個文件中的數據替換txt文件中特定位置的數據

  • September 9, 2014

我有以下格式的文本文件:

$data This is the experimental data    
good data
This is good file
datafile
1 4324 3673 6.2e+11 7687 67576
2 3565 8768 8760 5780 8778          "This is line '2'"
3 7656 8793 -3e+11 7099 79909
4 8768 8965 8769 9879 0970
5 5878 9879 7.970e-1 9070 0709799
.
.
.
100000 3655 6868 97879 96879 69899
$.endfile

我想用其他兩個文本文件中的數據替換第 2 行和第 4 列的數據,這些文本文件各有 99999 行。

如何使用 或任何其他 unix 命令執行此awk操作sed?請注意,列分隔符是空格。

其他兩個文本文件各有 99999 行,格式如下:

12414
12421
36347
3.4e+3
-3.5e22
987983
.
.
.
87698

由於您沒有要求 100% 的awk解決方案,我將提供一個混合體,(a) 可以說更容易理解,並且 (b) 不會強調awk的記憶體限制:

awk '
   $1 == 2 { secondpart = 1 }
      { if (!secondpart) {
               print > "top"
        } else {
               print $1, $2 > "left"
               print $5, $6, $7, $8, $9 > "right"
        }
      }' a
(cat top; paste -d" " left b c right) > new_a
rm top left right

或者我們可以刪除其中一個臨時文件並通過一個命令縮短腳本:

(awk '
   $1 == 2 { secondpart = 1 }
      { if (!secondpart) {
               print
        } else {
               print $1, $2 > "left"
               print $5, $6, $7, $8, $9 > "right"
        }
      }' a; paste -d" " left b c right) > new_a
rm left right

這將在輸出行的末尾放置一些額外的空格,並且 a如果任何行的欄位(列)超過九個,它將失去文件中的數據。如果這些是問題,它們可以很容易地解決。

一個尷尬的方式:

awk '{if(FNR==NR){f2[FNR+1]=$1;} 
     else{
       if(FNR==1){k++;} 
       if(k==1){f3[FNR+1]=$1} 
       else{if($1~/^[0-9]+/ && $1>1){$3=f2[$1];$4=f3[$1];} 
        print}
 }}' file2 file3 file1 

為清楚起見,這與註釋腳本編寫的內容相同:

#!/usr/local/bin/gawk -f

{
   ## NR is the current line number, irrespective of 
   ## which input file is being read. FNR is the line 
   ## number of the current file. It is reset to 1 each 
   ## time a new file is opened. Therefore, FNR will be 
   ## equal to NR only while the 1st file is being read.
   if(FNR==NR){
       ## If this is the 1st file, save its 1st field
       ## in the array f2. The key of the array is the
       ## line number of the current file plus one. This is
       ## because you want to start modifying from row '2' onwards.
       ## Therefore, presumably, you want the 1st row of file2 to
       ## be the value for row '2' of your data file..
       f2[FNR+1]=$1;
   } 
   ## If this is not the 1st file
   else{
       ## If this is the 1st line of the current file
       if(FNR==1){
           ## Increase the value of the variable k by 1.
           k++;
       } 
       ## If k is currently 1, this means that the above has only
       ## been run once so we are currently reading the 1nd file.
       if(k==1){
           ## Save the 1st field of this file (file3 in your example)
           ## in the array f3. The key of the array is the
           ## line number of the current file plus one. 
           f3[FNR+1]=$1
       }
       ## If k is not 1, we are reading the 3rd file. In this case, 
       ## your actual data.
       else{
           ## If the 1st field is a number and is greater than 1.
           ## In other words, if this is one of the lines you want
           ## to change. 
           if($1~/^[0-9]+/ && $1>1){
               ## Set the 3rd field to be the value saved in the array
               ## f2 for the value of $1.  
               $3=f2[$1];
               ## Set the 4th field to be the value saved in the array
               ## f3 for the value of $1. 
               $4=f3[$1];
           } 
           ## Print the current line. Since this is outside the
           ## previous if block, it will print all lines irrespective
           ## of whether they've been modified. 
           print;
       }
   }
}

Perl 方式:

perl -lane 'BEGIN{
   open(A,"file2"); while(<A>){chomp; $f2{$.+1}=$_;} 
   open(B,"file3"); while(<B>){chomp; $f3{$.+1}=$_;}} 
   if($F[0]=~/^\d+$/ && $F[0]>1){$F[2]=$f2{$F[0]}; $F[3]=$f3{$F[0]}}
    print "@F"' file1

解釋

  • -lane:l將自動從每個輸入行的末尾刪除尾隨換行符(與 相同)並為每個語句chomp添加一個換行符。printa自動將空白處的每個輸入行拆分為@F數組,使 perl 像 awk 一樣執行。意思是“在輸入文件的每一行執行由提供的n腳本。-e
  • BEGIN{...}:這是在讀取輸入文件之前執行的。在這種情況下,我打開每個額外的文件並將它們的內容保存在%f2%f3雜湊中。awk這與我上面使用的數組基本相同。
  • if($F[0]=~/^\d+$/ && $F[0]>1){...}: 同樣,這與 awk 腳本中的邏輯相同。它將用每個文件的相應條目替換欄位。
  • print "@F":這將列印所有欄位。

引用自:https://unix.stackexchange.com/questions/154352