里面有 $@ 变量的情况

里面有 $@ 变量的情况

我希望以下脚本允许用户选择 --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}将扩展。wordvar

答案3

如果您使用 bash,另一个选择是

for filename in "${@:2}"

这将为您提供论点,从第二个论点开始。 POSIX 没有指定这一点,因此某些系统可能不支持它。有些 shell 可能具有相同的功能,但使用不同的语法。

相关内容