2016-05-01 14 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"