我希望以下脚本允许用户选择 --header,然后插入 file* 作为文件名,以向所有有效文件添加标头。
#!/bin/bash
case "$1" in
--header )
for filename in "$@"
do
sed -i -e '1 e cat header' "$filename"
done
;;
--footer )
footer=~/dev/sed/footer
for filename in "$@"
do
cat "$footer" >> "$filename"
done
;;
esac
运行该工具执行 ./tool --header file* 会导致以下错误: sed: 无法识别的选项 '--header'
我知道这是因为 $@ 变量试图匹配第一个变量输入(--header),但我不知道如何阻止它
答案1
要从 $@ 中删除第一个元素,请使用shift
.
#!/bin/bash
opt=$1
shift
case "$opt" in
--header )
for filename in "$@" ; do
sed -i -e '1 e cat header' "$filename"
done
;;
--footer )
footer=~/dev/sed/footer
for filename in "$@" ; do
cat "$footer" >> "$filename"
done
;;
esac
答案2
问题是,当您运行循环(over "$@"
)时,该选项仍然是您循环的列表的第一个元素。您可以在循环之前删除$@
with的第一个元素。shift
我更喜欢将命令行解析和操作分开:
#!/bin/sh
unset do_header
unset do_footer
# loop until end of valid options...
while true; do
case $1 in
--header) do_header=1 ;;
--footer) do_footer=1 ;;
*) # assume end of options
break
esac
shift # we have processed a valid option, shift it off the list
done
# create a temporary file that we will use multiple times
tmpfile=$(mktemp)
# remove temporary file on normal exit (in bash, also on TERM/INT)
trap 'rm -f "$tmpfile"' EXIT
# For each file, copy it to the temporary file,
# then add header and footer as requested.
# Since we clobber the original file with the redirection,
# we won't be modifying permissions on the file.
# At this point, the valid options (any number of
# --header and --footer options) have been shifted off
# the list of arguments, so the $@ array now presumably only
# contains pathnames of files that are to be modified.
for pathname do
cp -- "$pathname" "$tmpfile"
cat ${do_header:+"header"} "$tmpfile" ${do_footer:+"footer"} >$pathname
done
此外,这还允许通过一次调用将页眉和页脚添加到一组文件中。
如果变量已设置且不为空,则参数替换${var:+word}
将扩展。word
var
答案3
如果您使用 bash,另一个选择是
for filename in "${@:2}"
这将为您提供论点,从第二个论点开始。 POSIX 没有指定这一点,因此某些系统可能不支持它。有些 shell 可能具有相同的功能,但使用不同的语法。