2016-05-01 12 views
0

我需要一個bash腳本,它應該執行以下操作: - 從輸入文件中逐行讀取格式爲:[Environment] = [file name] = [property key] = [property value] - 它將通過根據輸入文件替換$ SOURCE目錄中的所有屬性來修改所有文件。 現在我被困在「替換和計數」的地步。替換和計數bash無法通過awk和sed

的代碼,直到「替換和計數」相:

PROPERTIES_LIST=/home/user/test_scripts/envPropList.txt 

SOURCE=/home/user/test_scripts/source-directory 

PROPERTIES_LOCATION=/WEB-INF/classes/ 

PROPERTIES_SOURCE=$SOURCE$PROPERTIES_LOCATION 

ENV=$1 
echo "> Update for ENVIRONMENT: $ENV... Please wait!" 

NR=1 
while read line; do 
    IFS== read env prop <<< "$line" 
    if [[ $env == $ENV]] 
    then 
     IFS== read file key value <<< "$prop" 
     if [[ -z $file ]] || [[ -z $key ]] || [[ -z $value ]] 
     then 
      echo "> [ERROR] [LINE $NR] - WRONG/MISSING PROPERTY: $line" 
     else 
      //MODIFY $file BY REPLACE AND COUNT 
      //IF $key IS NOT FOUND AT ALL AN ERROR MESSAGE SHOULD BE DISPLAYED. ITERATION SHOULD CONTINUE 
      //IF $key IS FOUND MORE THEN ONCE, A WARNING MESSAGE SHOULD BE DISPLAYED. ITERATION SHOULD CONTINUE 

      echo "done" 
     fi 
    fi 
    NR=$(($NR + 1)) 
done <$PROPERTIES_LIST 

我曾嘗試以下沒有成功沒有成功,因爲在屬性值可以是任何字符(如:&,/,.... ):

COUNT=$(grep -c "$key" $PROPERTIES_SOURCE$file) 
sed -i "s/${OLD}/${NEW}/g" $PROPERTIES_SOURCE$file 

awk中也沒有發揮預期:

DEST=/home/user/test_scripts/test.txt 
OLD='asd.asd' 
NEW='test/test?test.test&test=test' 
COUNT=$(grep -c "$OLD" $DEST) 
#sed -i "s/#${OLD}#/#${NEW}#p/g" $DEST 
#echo "$OLD=$NEW" 
echo "nr de rezultate: "$COUNT 
awk -v OLD=$OLD -v NEW=$NEW ' 
    ($0 ~ OLD) {gsub(OLD, NEW); count++}1 
    END{print count " substitutions occured."} 
' "$DEST" 

而對於輸入文件:

asd.asd 
ewrqfg 
qweasd.asdqwreqe 
asd asd.asd 
egd 
test 

我有以下的輸出:

test/test?test.testasd.asdtest=test 
ewrqfg 
qwetest/test?test.testasd.asdtest=testqwreqe 
test/test?test.testasd asdtest=test.asd 
egd 
test 

如果我從$ NEW刪除 「&」,一切順利。

回答

0

你不發表您的預期輸出,所以這是一個猜測,但是這可能是你想要的東西:你不能使用GSUB()

$ cat tst.sh 
dest='file' 
old='asd.asd' 
new='test/test?test.test&test=test' 
count=$(grep -c "$old" "$dest") 
#sed -i "s/#${old}#/#${new}#p/g" "$dest" 
#echo "$old=$new" 
echo "nr de rezultate: $count" 
awk -v old="$old" -v new="$new" ' 
    { 
     head = "" 
     tail = $0 
     lgth = length(old) 
     while (start = index(tail,old)) { 
      head = head substr(tail,1,start-1) new 
      tail = substr(tail,start+lgth) 
      count++ 
     } 
     print head tail 
    } 
    END { print count+0, "substitutions occured." } 
' "$dest" 

$ ./tst.sh file 
nr de rezultate: 3 
test/test?test.test&test=test 
ewrqfg 
qwetest/test?test.test&test=testqwreqe 
asd test/test?test.test&test=test 
egd 
test 
3 substitutions occured. 

注意的,那麼你會在escaping hell just like if you used sed,而不是你有使用index()和substr(),因爲它們在文字字符串上操作,而不是在替換中的正則表達式和反向引用。

另外:總是引用你的shell變量,並且在shell中,所有大寫字母的使用都是按照慣例爲導出變量保留的,而在awk和shell中,你應該避免使用所有大寫變量名稱,以避免與內置變量衝突。

0

這是我通過「sed」命令解決問題,這正是我所需要的。我不確定它運行的速度有多快,因爲在腳本運行時會有很多屬性需要更改。

夥計們,請有過我的解決方案進行審查,建設性的反饋意見表示歡迎:

PROPERTIES_SOURCE=$SOURCE$PROPERTIES_LOCATION 

MEDIUM=$1 
echo "> Update release for ENVIRONMENT: "$MEDIUM"... Please wait!" 

if [[ -z $1 ]] 
then 
    echo "> [ERROR] - Illegal script use. You have to send one of the following parameters representing environment name which will be updated:" 
    echo "> [ERROR] - DEV ST UAT PROD" 
    echo "> [ERROR] - Example: ./updateEnv.sh PROD" 
    exit 
fi 

nr=1 
while read -r line; do 
    IFS== read -r env prop <<< "$line" 
    if [[ $env == $MEDIUM ]] 
    then 
     IFS== read -r file key value <<< "$prop" 
     if [[ -z $file ]] || [[ -z $key ]] || [[ -z $value ]] 
     then 
      echo "> [ERROR] [LINE $NR] - wrong or missing property: $line" 
     else 
      esc_key=$(echo $key | sed -e 's/\./\\./g') 
      esc_val=$(echo $value | sed -e 's/\&\|\.\|\\\|\/\|\%/\\&/g') 
      occurances=$(grep -c "$key=" "$PROPERTIES_SOURCE$file") 
      if [[ $occurances > 1 ]] 
      then 
       echo "> [WARNING] [LINE $NR] - key found $occurances times: $key" 
      elif [[ $occurances < 1 ]] 
      then 
       echo "> [ERROR] [LINE $NR] - key was not found: $key" 
      fi 
      sed -i "s/${esc_key}=.*/${esc_key}=${esc_val}/g" $PROPERTIES_SOURCE$file 
     fi 
    fi 
    nr=$(($nr + 1)) 
done <$PROPERTIES_LIST 

此外,我使用awk成功也有一些sed的在我的變量,這是不同的sed逃逸字符串:

STRING_OLD='asd.asd' 
STRING_NEW='[email protected]#$%^&*()_+-=[]\{}|;"<>~`' 
OLD=$(echo $STRING_OLD | sed -e 's/\./\\\\./g') 
NEW=$(echo $STRING_NEW | sed -e 's/\&\|\\/\\\\&/g') 

和替換的awk代碼將是這樣的:

awk -v OLD="$OLD" -v NEW="$NEW" ' 
    BEGIN {print "OLD:"OLD" and NEW:"NEW} 
     ($0 ~ OLD) {gsub(/OLD=.*/,OLD=NEW);}1 
' "$DEST" > "DEST.tmp" mv "DEST.tmp" "$DEST"