We hope to replace the Line 3 of file001 to file600 with corresponding line in the instruction.txt, and is there any possible solution in bash language? I thought maybe I could write a script with sed
or awk
command, but I couldn't come up with it. Any help would be appreciated. Thanks!
The file001 to file600 contain many cartesian coordinates and are of the same format. E.g. file001 is as follows:
3.02 5.46 8.94
4.55 3.22 4.35
0.00 0.00 0.00 # this is the wrong line and we want to get it replaced
2.34 3.32 5.47
...
The instruction.txt file is:
file001
3.25 1.13 6.10 #this means to replace the 3rd line of "file001" with "3.25 1.13 6.10"
file002
6.01 1.17 -0.32 #this means to replace the 3rd line of "file002" with "6.01 1.17 -0.32"
...
CodePudding user response:
My solution look pretty messed up, but it works :) you can try it, let me know if it works for you.
for i in `cat instruction.txt | awk 'NR % 2 == 1 { printf $0; printf "\n" }'`; do
outp=`awk '/'"$i"'/{getline; print}' instruction.txt`;
sed -i '3s/0.00 0.00 0.00/'"$outp"'/' $i;
done
First, I try to filter all the odd lines that contain filename, and assign it to the variable $i
:
cat instruction.txt | awk 'NR % 2 == 1 { printf $0; printf "\n" }'
Then get the next line of every $i
, which is fix value and assign it to the variable $outp
:
outp=`awk '/'"$i"'/{getline; print}' instruction.txt`
And finally, replace the wrong 3rd line with 2 variables I just received.
sed -i '3s/0.00 0.00 0.00/'"$outp"'/' $i
CodePudding user response:
Here would be a solution with GNU awk >= 4.1.0
(I didn't test the inplace
part because I don't have the correct version at hand):
awk -i inplace '
BEGIN {
while ( (getline filename < ARGV[1] > 0) && (getline data < ARGV[1] > 0) )
instructions[filename] = data
close(ARGV[1])
delete ARGV[1]
}
FNR == 1 {
filename = FILENAME
sub(/.*\//,"",filename)
}
FNR == 3 && filename in instructions {
print instructions[filename]
next
}
1
' instructions.txt file[0-9][0-9][0-9]
The code first first loads instructions.txt
then modifies the 3rd line of the other files if their "basename" is found in the instructions
CodePudding user response:
while read -r line; do
if [[ $(sed -E 's/^([^ ]*).*/\1/' <<< "$line") =~ "file" ]]; then
file=$line
elif [[ $(sed -E 's/^([^ ]*).*/\1/' <<< "$line") =~ [0-9.] ]]; then
sed -i.bak "3c$line" "$file"
fi
done < instructions.txt