2016-08-19 93 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