我有这个配置文件
# 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'
答案 0 :(得分: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为第3个arg匹配()。如果您必须在UNIX环境中操作文本,请阅读Arnold Robbins的“Effective Awk Programming,4th Edition”一书。
现在回到你的问题:
这是您正在尝试做的语法:
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”,但您在regexp上下文中使用它(您可以使用sed执行所有操作),因此我也在awk命令的regexp上下文中使用它并命名为awk变量“regexp” “为了清晰起见,而不是”字符串“(它只是一个变量名,但没有隐藏的含义)。
如果您确实希望将其视为字符串而非正则表达式,那么它应该是:
awk -v string="$some_string" -v line="$some_line" '{print} index($0,string){print line}' file
上面唯一的警告是,当awk变量从它们初始化时,shell变量中的反斜杠将被展开,因此\t
将成为文字制表符。如果这是不合需要的,请告诉我们,我们可以提供一种替代语法来启动不扩展反斜杠的awk变量,请参阅http://cfajohnson.com/shell/cus-faq-2.html#Q24。
答案 1 :(得分: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}#"
答案 2 :(得分: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