我有一个bash脚本,它将文件的内容传递给一系列用户定义的函数,每个函数都对stdin执行sed操作,并将输出发送到stdout。
例如:
#!/bin/bash
MOD_config ()
{
sed 's/config/XYZ/g'
}
MOD_ABC ()
{
sed 's/ABC/WHOA!/g'
}
cat demo.txt \
| MOD_config \
| MOD_ABC
到目前为止一切顺利。一切都很好。
现在我想允许通过脚本命令行指定的其他模式更改对。例如,我想允许用户运行以下任何一个:
demo.sh # changes per script (MOD_config and MOD_ABC)
demo.sh CDE 345 # change all 'CDE' to '345'
demo.sh CDE 345 AAAAA abababa # .. also changes 'AAAAA' to 'abababa'
所以我尝试将其添加到脚本中:
USER_MODS ()
{
if [ $# -lt 1]; then
#just echo stdin to stdout if no cmd line args exist
grep .
else
STARTING_ARGC=$#
I=1
while [ $I -lt $STARTING_ARGC ]; then
sed "s/$1/$2/g"
shift
shift
I=`expr $I + 2`
done
fi
}
cat demo.txt \
| MOD_config \
| MOD_ABC \
| USER_MODS
这种方法只有在我没有命令行args或者我只有两个时才有效。但是,在命令行中添加其他args无效。
不确定如何将while循环的一次迭代的stdout发送到下一次迭代的stdin。我认为这是我问题的症结所在。
有解决方法吗?或者我应该采取不同的方法吗?
答案 0 :(得分:2)
要拥有动态管道列表,您需要一个递归解决方案。有一个函数应用一组修改,然后用两个较少的参数调用自己。如果函数没有参数,那么只需调用cat
即可将stdin复制到stdout不变。
mod() {
if (($# >= 2)); then
search=$1
replace=$2
shift 2
sed "s/$search/$replace/g" | mod "$@"
else
cat
fi
}
# Apply two base modifications, plus any additional user mods ("$@")
mod config XYZ ABC 'WHOA!' "$@"
答案 1 :(得分:2)
注释:有超过2个参数,你的seds被执行,但是在第一个已经消耗了所有输入之后。相反,你想建立一系列sed命令。
#!/bin/bash
mod_config() { sed 's/config/XYZ/g'; }
mod_abc() { sed 's/ABC/WHOA!/g'; }
user_mods() {
local IFS=';'
local sed_subs=()
while (($#>=2)); do
sed_subs+=( "s/$1/$2/g" )
shift 2
done
# at this point you have an array of sed s commands (maybe empty!).
# Just join then with a semi colon using the IFS already set
sed "${sed_subs[*]}"
}
cat demo.txt \
| mod_config \
| mod_abc \
| user_mods "$@" # <--- don't forget to pass the arguments to your function
并祈祷您的用户不会输入会混淆sed
的内容,例如斜杠!
(抱歉,我把你所有的变量都降低了。大写的东西太丑了。)
答案 2 :(得分:1)
试试这个,使用递归调用来查看每次调用USER_MODS的替换对列表。
#!/bin/bash
MOD_config ()
{
sed 's/config/XYZ/g'
}
MOD_ABC ()
{
sed 's/ABC/WHOA!/g'
}
USER_MODS ()
{
if [ $# -lt 1 ]; then
#just echo stdin to stdout if no args exist
grep .
else
# grap the next two arguments
arg1=$1
arg2=$2
# remove them from the argument list
shift
shift
# do the replacement for these two and recursivly pipe to the function with
# the new argument list
sed "s/$arg1/$arg2/g" | USER_MODS $@
fi
}
cat demo.txt \
| MOD_config \
| MOD_ABC \
| USER_MODS $@