簡體   English   中英

同時迭代兩個數組-bash n sed

[英]Iterate two arrays simultaneously - bash n sed

我需要在bash中同時執行兩個數組並使用sed將每個單獨文件中第二個數組中的單詞替換為單詞的幫助。 有兩個列表:

List1-包含目錄的名稱,在每個目錄中具有相似的參數文件“ surfnet.par”(不同目錄中的文件具有相同的名稱“ surfnet.par”)

List1.txt

3IT6_1
3IT6_3
3IT6_6
3IT6_9
3IT6_11
3IT6_12
3IT6_19
3IT6_23
3IT6_54
3IT6_62

List2-包含與每個目錄相對應的數字,這些目錄必須用不同目錄中存在的文件“ surfnet.par”中的特定單詞(單次出現)替換

List2.txt

11351
11357
11371
11384
11350
11373
11383
11365
11377
11382

使它仍然清晰

我想將List1的目錄“ 3IT6_1”中“ surfnet.par”中的“ Resnum”替換為List2的“ 11351”,同樣,將3IT6_2的“ surfnet.par”中的相同單詞替換為11357,將3IT6_3替換為11357 ,帶有11371的3IT6_6等。

我嘗試將列表推送到數組,然后使用for循環替換單詞,但這樣做失敗,因為它采用了List2的第一個值,並替換了不同目錄中的所有“ surfnet.par”文件。 我一直在使用的腳本如下:

#!/bin/bash

declare -a dir
declare -a res

dir=(`cat "List1.txt" `)
res=(`cat 'List2.txt'`)

for i in "${dir[@]}"
    do 
        echo $i
        cd $i
        sed -e "s/Resnum/${res$[0]}/g" surfnet.par > surfnet2.par
        cd ..
    done

如果您能幫助我解決此代碼並指出需要進行的修改,我將非常感謝。 萬一我的代碼沒有任何意義,請使用bash,awk,sed或perl向我提供解決方案

我認為您可能比您想象的要更接近解決方案。 這是bash中的一種情況,其中使用c-style循環並在索引上進行迭代非常方便。 對您的代碼進行以下一些細微更改應該可以起作用,請嘗試一下(注意:我在cd上添加了一項檢查,並使用起始目錄作為current目錄來啟用絕對路徑):

#!/bin/bash

declare -a dir
declare -a res

dir=( $(<List1.txt) )
res=( $(<List2.txt) )

current="$PWD"

for ((i = 0; i < ${#dir[@]}; i++))
    do 
        cd "$current/${dir[i]}" || {
            echo "failed to change to ${dir[i]}"
            continue
        }
        printf "%3d  %-8s Resnum -> %s\n" $i ${dir[i]} ${res[i]}
        sed -e "s/Resnum/${res[i]}/g" surfnet.par > surfnet2.par
    done

使用范例

測試了帶有cdsed調用的ListX.txt文件。

$ bash resnum.sh
  0  3IT6_1   Resnum -> 11351
  1  3IT6_3   Resnum -> 11357
  2  3IT6_6   Resnum -> 11371
  3  3IT6_9   Resnum -> 11384
  4  3IT6_11  Resnum -> 11350
  5  3IT6_12  Resnum -> 11373
  6  3IT6_19  Resnum -> 11383
  7  3IT6_23  Resnum -> 11365
  8  3IT6_54  Resnum -> 11377
  9  3IT6_62  Resnum -> 11382

注意:在bash中用於indexed數組時,不需要在索引變量上使用$ (例如${dir[$i]}${dir[i]}一樣好((..))與在循環聲明中一樣,將其視為包含在((..))

注意2:您可能應該在調用cd更改為所需目錄之前,在循環的頂部添加兩個值均可用的驗證:

        ## validate both values available
        [ -z ${dir[i]} -o -z ${res[i]} ] && {
            echo "'${dir[i]}' or '${res[i]}' missing."
            continue
        }

您的問題帶有Perl標簽,因此我認為Perl解決方案是可以接受的

您的問題不是很清楚,但是我認為該程序應該可以為您提供幫助

use strict;
use warnings;
use v5.10.1;
use autodie;

my @dirs = slurp('Listdirs204.txt');
my @res  = slurp('LastHetatmRes.txt');

die "File sizes don't match" unless @dirs == @res;

for my $i ( 0 .. $#dirs ) {

    my ($dir, $res) = ($dirs[$i], $res[$i]);
    my $file        = "$dir/surfnet.par";

    my @lines = slurp($file);
    s/Resnum/$res/g for @lines;

    open my $fh, '>', $file;
    print $fh "$_\n" for @lines;
    close $fh;
}


sub slurp {
    open my $fh, '<', shift;
    my @lines = <$fh>;
    chomp @lines;
    @lines;
}

如果您不想輸入太多,可以這樣做

while read d s; do sed 's/target/'"$s"'/g' "$d"/f.txt > "$d"/f2.txt; done < <(paste list1 list2)

用您的搜索詞f.txt f2.txt list1list2適當地替換target為您使用的文件名。 應該清楚是哪個。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM