파일의 숫자를 어떻게 조작합니까?

파일의 숫자를 어떻게 조작합니까?

이미지와 *.txt 파일을 첨부했습니다https://1drv.ms/t/s!Aoomvi55MLAQh1jODfUxa-xurns_ 샘플 작업지의 일부입니다. 이 파일에서 반응은 "r1f", "r2f", "r3f"...등으로만 시작됩니다. 각 반응에 대해 반응 속도는 몇 줄 뒤에 표시되며 앞에 "+" 기호가 표시됩니다. 응답률의 첫 번째와 세 번째 숫자를 +/-75%로 변경하고 싶습니다. 따라서 각 반응에는 4개의 변형 값이 있습니다. 따라서 Prob01.txt 파일에 6개의 반응이 있는 경우 각각 하나의 반응 속도 변경만 있는 6*4=24 txt 파일을 갖고 싶습니다. 즉, 첫 번째 반응에만 반응 1의 4가지 변경 사항이 포함된 Prob01.txt 파일 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)

보시다시피, 첫 번째와 세 번째 값에 1.75를 곱하는 awk 부분이 있습니다. 그런 다음 필요에 따라 조정할 수 있습니다.

결과:

:/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

관련 정보