2016-08-19 45 views
-1

我有了如何在sed命令行中使用變量?

# some other configuration settings 
..... 
wrapper.java.classpath.1=/opt/project/services/wrapper.jar 
wrapper.java.classpath.2=/opt/project/RealTimeServer/RTEServer.jar 
wrapper.java.classpath.3=/opt/project/mysql-connector-java-5.1.39-bin.jar 
..... 
# some other configuration settings 

該配置文件,我希望它看起來像這樣

# some other configuration settings 
..... 
wrapper.java.classpath.1=/opt/project/services/wrapper.jar 
wrapper.java.classpath.2=/opt/project/RealTimeServer/RTEServer.jar 
wrapper.java.classpath.3=/opt/project/mysql-connector-java-5.1.39-bin.jar 
wrapper.java.classpath.4=/opt/project/RealTimeServer/some_other.jar 
..... 
# some other configuration settings 

所以我寫了這個bash shell的

#!/bin/bash 

CONF_FILE=$1 
JAR_FILE=$2 
DIR=$3 

# Get the last wrapper.java.classpath.N=/some_path line 
CLASSPATH=`awk '/classpath/ {aline=$0} END{print aline}' $CONF_FILE` 
echo $CLASSPATH 

# Get the left side of the equation 
IFS='=' read -ra LS <<< "$CLASSPATH" 

# Get the value of N 
NUM=${LS##*\.} 

# Increment by 1 
NUM=$((NUM+1)) 
echo $NUM 

NEW_LINE="wrapper.java.classpath.$NUM=$DIR/$JAR_FILE" 
echo $NEW_LINE 

# Append classpath line to conf file 
sed "/$CLASSPATH/a \\${NEW_LINE}" $CONF_FILE 

我把它叫做這樣

./append_classpath.sh some_file.conf some_other.jar /opt/project/RealTimeServer 

但我得到

sed: -e expression #1, char 28: unknown command: `o' 
+3

是什麼你的變量在這裏? – heemayl

+1

給我們一個所有的信息。測試文件,變量以及您正在使用的操作系統和外殼。 –

+0

在黑暗中拍攝:嘗試'$ {some_string}'。 $似乎只能看到變量名的第一個字母。 $ {some_line}也一樣。 – steffen

回答

0

我剛纔看到你的shell腳本。 shell是調用工具的環境,它不是操縱文本的工具。用於處理文本的標準通用UNIX工具是awk。您的整個shell腳本可以縮減爲:

$ dir="/opt/project/RealTimeServer" 
$ jar_file="some_other.jar" 
$ awk -v new="$dir/$jar_file" 'p~/classpath/ && !/classpath/{match(p,/([^=]+\.)([0-9]+)=/,a); print a[1] (++a[2]) "=" new} {print; p=$0}' file 
# some other configuration settings 
..... 
wrapper.java.classpath.1=/opt/project/services/wrapper.jar 
wrapper.java.classpath.2=/opt/project/RealTimeServer/RTEServer.jar 
wrapper.java.classpath.3=/opt/project/mysql-connector-java-5.1.39-bin.jar 
wrapper.java.classpath.4=/opt/project/RealTimeServer/some_other.jar 
..... 
# some other configuration settings 

上面的代碼使用GNU awk for第三個arg來匹配()。如果您將不得不在UNIX環境中操作文本,請閱讀Arnold Robbins編寫的「有效的Awk編程」第4版。


現在回到你的問題:

這是語法,你正在做什麼:

sed '/'"$some_string"'/a '"$some_line" "$some_file" 

但不這樣做,或者你會譴責自己神祕,不可移動,不可維護,剝洋蔥,逃避一切地獄(見Is it possible to escape regex metacharacters reliably with sed)!

sed是針對個別行的簡單替代,就是這樣。除此之外,例如你嘗試,你應該用AWK:

awk -v regexp="$some_string" -v line="$some_line" '{print} $0~regexp{print line}' file 

注意,雖然你的shell變量命名爲「some_string」你在正則表達式上下文中使用它(你可以用SED做的),所以我把它用在也是awk命令中的一個正則表達式上下文,爲了清楚起見,它命名awk變量「regexp」而不是「string」(它只是一個變量名,儘管沒有隱藏含義)。

如果你真的我希望它作爲一個字符串,而不是一個正則表達式處理,那麼這會是:

awk -v string="$some_string" -v line="$some_line" '{print} index($0,string){print line}' file 

唯一要注意上面的是,在shell變量反斜槓將擴大在AWK變量從它們初始化,所以\t,例如,將成爲一個字面標籤字符。如果這是不可取的,請告訴我們,我們可以爲啓動awk變量提供另一種語法,但不會擴展反斜槓,請參閱http://cfajohnson.com/shell/cus-faq-2.html#Q24

+0

謝謝,但我試過了,它沒有追加行。請注意,我在包裝線前後有行。我會編輯我的帖子以反映這一點。 –

+0

你還錯過了這裏匹配的單引號嗎? sed'/'「$ some_string」'/ a'「$ some_line」'「$ some_file」。在我修正語法之後,我也使用了這個功能,但沒有成功。 –

+0

對,如果你的真實輸入看起來不像你的樣本輸入,那麼所有的投注都關閉。我可能錯過了sed命令的引用,不要緊,因爲它不應該被使用。其實這只是一個報價太多。 –

0

sed命令將在您的變量中出現斜槓問題。 尋找一些獨特的分隔符,如#和嘗試像

CLASSPATH="wrapper.java.classpath.4=/opt/project/RealTimeServer/some_other.jar" 
NEW_LINE="wrapper.java.classpath.5=your/data.rar" 

echo "# some other configuration settings 
..... 
wrapper.java.classpath.1=/opt/project/services/wrapper.jar 
wrapper.java.classpath.2=/opt/project/RealTimeServer/RTEServer.jar 
wrapper.java.classpath.3=/opt/project/mysql-connector-java-5.1.39-bin.jar 
wrapper.java.classpath.4=/opt/project/RealTimeServer/some_other.jar 
..... 
# some other configuration settings 

Some more config lines 
" | sed "s#${CLASSPATH}#&\n${NEW_LINE}#" 
+0

它會遇到更多字符而不僅僅是斜槓,例如任何BRE regexp元字符,反斜槓後面跟一個數字或'&'。請參閱http://stackoverflow.com/q/29613304/1745001瞭解如何使用sed強力執行此操作。 –

0

這是一個通純bash的解決方案 - 它應該是罰款,如果配置文件不是很大

pfx=wrapper.java.classpath. 
while IFS= read -r line; do 
    if [[ $line == $pfx*=* ]]; then 
    lastclasspath=$line 
    elif [[ -n $lastclasspath ]]; then 
    newline=${lastclasspath#$pfx} 
    num=${newline%%=*} 
    newline="$pfx$((num+1))=$DIR/$JAR_FILE" 
    echo "$newline" 
    unset lastclasspath 
    fi 
    echo "$line" 
done <$CONF_FILE