[英]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
使用范例
測試了帶有cd
和sed
調用的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 list1
和list2
適當地替換target
為您使用的文件名。 應該清楚是哪個。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.