I need help with executing two arrays simulataneously in bash and using sed to replace a word with the words in the second array in each separate file. There are two lists:
List1 - contains the names of the directories, which have similar parameter file "surfnet.par" in each directory (the file in different directories have the same name "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 - contains numbers corresponding to each directory which has to be replaced with a specific word (single occurrence) in the file "surfnet.par" existing in different directories
List2.txt
11351
11357
11371
11384
11350
11373
11383
11365
11377
11382
To make it still clear
I want to replace a word "Resnum" in "surfnet.par" in the directory "3IT6_1" of List1 with "11351" of List2, likewise, replace the same word in "surfnet.par" of 3IT6_2 with 11357, 3IT6_3 with 11357, 3IT6_6 with 11371 and so on.
I have tried pushing the list to array and then using a for loop to replace the word, but failed in doing so, as it took the first value of List2 and replace in all "surfnet.par" files in different directories. The script I have been using is as below:
#!/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
I will appreciate it very much, if any of you can help me resolve this code and point out the modification that needs to be done. In case, my code doesn't make any sense please provide me the solution using bash, awk, sed or perl
I think you may have been a whole lot closer to a solution than you thought. This is one situation in bash where making use of a c-style
loop and iterating on an index can come in very handy. The following slight changes to your code should work, give it a try (note: I added a check on cd
and used the starting directory as current
to enable use of absolute paths):
#!/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
Example Use
Tested with your ListX.txt files with cd
and sed
calls commented out.
$ 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
Note: in bash for indexed
arrays, the use of the $
on the index variable is not required. (eg ${dir[$i]}
is fine as ${dir[i]}
. It is treated the same as if it were enclosed in ((..))
as in the loop declaration.
Note2: you should probably add a validation that both values are available at the top of the loop before calling cd
to change to the desired directory:
## validate both values available
[ -z ${dir[i]} -o -z ${res[i]} ] && {
echo "'${dir[i]}' or '${res[i]}' missing."
continue
}
Your question bears a Perl tag so I assume that Perl solutions are acceptable
Your question isn't very clear, but I think this program should help you
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;
}
If you don't like to type too much, you can do this
while read d s; do sed 's/target/'"$s"'/g' "$d"/f.txt > "$d"/f2.txt; done < <(paste list1 list2)
appropriately replace target
with your search word, f.txt f2.txt list1
and list2
with the file names you use. It should be clear which is which.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.