我附上了图片和 *.txt 文件https://1drv.ms/t/s!Aoomvi55MLAQh1jODfUxa-xurns_ 示例工作文件的一部分。在这个文件中,反应仅以“r1f”、“r2f”、“r3f”......等开头。对于每个反应,反应速率位于几行后面,并带有“+”号。我想将反应率中的第一个和第三个数字更改为 +/-75%。因此每个反应都会有 4 个变化值。因此,如果 Prob01.txt 文件中有 6 个反应,那么我希望有 6*4=24 个 txt 文件,每个文件只有一个反应速率变化。这意味着仅对于第一反应,我需要四个 Prob01.txt 文件,其中包含反应 1 中的 4 个更改。
答案1
这个怎么样……绝对是一把大锤。
调用它以thisScript Prob01.txt 0.75 0.25
在每个反应上应用第一个 +/-75% 变化和第三个值 +/-25% 变化的组合,并将它们写入单独的文件
#!/bin/bash
#takes $inputFile $pct1 $pct3
#note $pct is the multiplier expressed as a decimal
#global variables
#$w : the line number and original figures, space separated
#$newFile : the new file name
#$o : the original figures in the original format
#$n : the new figures in the correct format
inputFile=$1
#strip the suffix (.txt) from the inputFile name
outFile=${inputFile%.*}
pct1=$2
pct3=$3
function domath {
# takes $value $multiplier
local m=$(echo 1+$2 | bc -l)
local theanswer=$(echo $1 $m | awk '{printf "%7.6E\n" , $1*$2}' | sed -E -e 's/[Ee]\+*/E/g' -e 's/^([^-])/+\1/g')
echo $theanswer
}
function makechange {
#takes $reaction $case
#compose new file name
newFile=${outFile}_$1_$(printf "%02g" $2).txt
#make a copy
cp $inputFile $newFile
#change the appropriate line
sed -i "${w[0]}s/$o/$n/" $newFile
}
#get all the reaction names
grep -Po "^r[0-9]+f(?=:)" Prob01.txt > stepA
#get all the figures and their line numbers in case duplicates occur
grep -Pon "^\+[^\!]*" Prob01.txt > stepB
for ((i=1; i<=$(cat stepA | wc -l); i++)); do
reaction=$(sed "${i}q;d" stepA)
figures=$(sed "${i}q;d" stepB | sed 's/:/ /g')
w=($figures)
#retrieve the old string
o=$(echo $figures | grep -Po "(?<= ).*")
#compose the new string for each of the 4 cases
for ((j=1; j<=4; j++)); do
case $j in
1)
n=$(echo "$(domath ${w[1]} $pct1) ${w[2]} ${w[3]}")
;;
2)
n=$(echo "$(domath ${w[1]} -$pct1) ${w[2]} ${w[3]}")
;;
3)
n=$(echo "${w[1]} ${w[2]} $(domath ${w[3]} $pct3)")
;;
4)
n=$(echo "${w[1]} ${w[2]} $(domath ${w[3]} -$pct3)")
;;
esac
#make the changes
makechange $reaction $j
done
done
#clean up
rm step{A..B}
答案2
这是 bash 中的一个时髦版本
#!/bin/bash
r=""
res=""
while read line; do
if [[ "$line" =~ ^(r[0-9]+f:[^ \t]+)[[:space:]]+\!+.+$ ]]; then
r="${BASH_REMATCH[1]}"
fi
if [[ "$line" =~ ^(\+[0-9]+\..+[0-9])[[:space:]]+\!+.+$ ]]; then
res="${BASH_REMATCH[1]}"
fi
if [[ -n "$r" ]] && [[ -n "$res" ]]; then
echo -e "$r\t\t$res"
r=""
res=""
fi
done < <(grep -E "^r[0-9]+f:|^\+[0-9]+\." /path/to/yourfile)
这将在您的字段之间插入 2 个“选项卡”,不知道这是否是您需要的。我的 grep 有点“宽”,如果你愿意,你可以调整它。
结果:
:/tmp$ bash script
r1f:O2+2PD=>2O-PD +7.000000E-02 +0.000000E00 +0.000000E00
r2f:C3H6+2PD=>C3H6-PD +9.800000E-01 +0.000000E00 +0.000000E00
r3f:C3H6+O-PD+PD=>C3H5-PD+OH-PD +2.747319E-01 +0.000000E00 +0.000000E00
r4f:H2+2PD=>2H-PD +4.600000E-02 +0.000000E00 +0.000000E00
r5f:H2O+PD=>H2O-PD +2.492452E-01 +0.000000E00 +0.000000E00
r6f:CO2+PD=>CO2-PD +5.000000E-03 +0.000000E00 +0.000000E00
对于你的 +75% 的事情,它让事情变得有点复杂,因为 bash 无法处理实数。所以,这是一个使用 bash 和 awk 的肮脏解决方案。
#!/bin/bash
while read line; do
if [[ "$line" =~ ^(r[0-9]+f:[^ \t]+)[[:space:]]+\!+.+$ ]]; then
r="${BASH_REMATCH[1]}"
fi
if [[ "$line" =~ ^(\+[0-9\.Ee-]+)[[:space:]]+(\+[0-9\.Ee-]+)[[:space:]]+(\+[0-9\.Ee-]+)[[:space:]]+\!+.+$ ]]; then
res1="${BASH_REMATCH[1]}"
res2="${BASH_REMATCH[2]}"
res3="${BASH_REMATCH[3]}"
res1=$(echo $res1 | awk '{ printf "%.6E",$1*1.75 }')
res3=$(echo $res3 | awk '{ printf "%.6E",$1*1.75 }')
fi
if [[ -n "$r" ]] && [[ -n "$res1" ]] && [[ -n "$res2" ]] && [[ -n "$res3" ]]; then
echo -e "$r\t\t+$res1\t\t$res2\t\t+$res3"
r=""
res1=""
res2=""
res3=""
fi
done < <(grep -E "^r[0-9]+f:|^\+[0-9]+\." /path/to/yourfiles)
正如你所看到的,那里有一个 awk 部分,它只是将你的第一个和第三个值乘以 1.75。然后您可以根据需要进行调整。
结果:
:/tmp$ bash script
r1f:O2+2PD=>2O-PD +1.225000E-01 +0.000000E00 +0.000000E+00
r2f:C3H6+2PD=>C3H6-PD +1.715000E+00 +0.000000E00 +0.000000E+00
r3f:C3H6+O-PD+PD=>C3H5-PD+OH-PD +4.807808E-01 +0.000000E00 +0.000000E+00
r4f:H2+2PD=>2H-PD +8.050000E-02 +0.000000E00 +0.000000E+00
r5f:H2O+PD=>H2O-PD +4.361791E-01 +0.000000E00 +0.000000E+00
r6f:CO2+PD=>CO2-PD +8.750000E-03 +0.000000E00 +0.000000E+00