web-dev-qa-db-ja.com

シェルスクリプトに渡される最後の引数を取得する

$1は最初の引数です。
$@はすべてです。

シェルスクリプトに渡された最後の引数を見つけるにはどうすればよいですか?

244
Thomas

これはちょっとしたハックです。

for last; do true; done
echo $last

これも非常に移植性が高く(再び、bash、ksh、shで動作するはずです)、引数をシフトしません。

ループする対象を指定しないと、forが暗黙的に引数をループするという事実と、forループ変数のスコープが設定されていないという事実を使用します。

160

これはBash専用です。

echo "${@: -1}"
271
$ set quick brown fox jumps

$ echo ${*: -1:1} # last argument
jumps

$ echo ${*: -1} # or simply
jumps

$ echo ${*: -2:1} # next to last
fox

デフォルト値 として解釈されないようにスペースが必要です。

77
Steven Penny

Bash 3.0以降の最も簡単な答えは

_last=${!#}       # *indirect reference* to the $# variable
# or
_last=$BASH_ARGV  # official built-in (but takes more typing :)

それでおしまい。

$ cat lastarg
#!/bin/bash
# echo the last arg given:
_last=${!#}
echo $_last
_last=$BASH_ARGV
echo $_last
for x; do
   echo $x
done

出力は次のとおりです。

$ lastarg 1 2 3 4 "5 6 7"
5 6 7
5 6 7
1
2
3
4
5 6 7
73
Kevin Little

次の長さと組み合わせたインデックスを使用します。

echo ${@:${#@}} 
27
Mark Byers

次はあなたのために働くでしょう。 @は引数の配列用です。 :はを意味します。 $#は引数の配列の長さです。したがって、結果は最後の要素になります。

${@:$#} 

例:

function afunction{
    echo ${@:$#} 
}
afunction -d -o local 50
#Outputs 50
25
Tahsin Turkoz

これは、最後の引数を前のすべての引数から分離するときに見つけました。答えのいくつかは最後の引数を取得しますが、他のすべての引数も必要な場合、それらはあまり役に立ちません。これははるかに優れています:

heads=${@:1:$(($# - 1))}
tail=${@:$#}
22
AgileZebra

これはすべてのPOSIX互換シェルで機能します。

eval last=\${$#}

ソース: http://www.faqs.org/faqs/unix-faq/faq/part2/section-12.html

19
poiuz

ここに私のソリューションがあります:

  • 可搬性が高い(すべてのPOSIX sh、bash、ksh、zsh)が動作するはずです
  • 元の引数をシフトしません(コピーをシフトします)。
  • 使用しない 悪の eval
  • リスト全体を反復しません
  • 外部ツールを使用しません

コード:

ntharg() {
    shift $1
    printf '%s\n' "$1"
}
LAST_ARG=`ntharg $# "$@"`
10
Michał Šrajer

Bash> = 3.0を使用している場合

echo ${BASH_ARGV[0]}
8
dusan

Ksh、zsh、およびbashの場合:

$ set -- The quick brown fox jumps over the lazy dog

$ echo "${@:~0}"
dog

そして「最後から次へ」の場合:

$ echo "${@:~1:1}"
lazy

ダッシュ(-nなど)で始まる引数の問題を回避するには、次を使用します。

$ printf '%s\n' "${@:~0}"
dog

shのスペースとグロブ文字を処理する正しい方法は次のとおりです。

$ set -- The quick brown fox jumps over the lazy dog "the * last argument"

$ eval echo "\"\${$#}\""
The last * argument

または、last varを設定する場合:

$ eval last=\${$#}; echo "$last"
The last * argument

そして「最後から次へ」の場合:

$ eval echo "\"\${$(($#-1))}\""
dog
4
Isaac
shift `expr $# - 1`
echo "$1"

これは、引数の数から1を引いた数だけ引数をシフトし、最初の(そして唯一の)残りの引数を返します。これが最後の引数になります。

私はbashでのみテストしましたが、shおよびkshでも動作するはずです。

2

非破壊的な方法でそれを行いたい場合、1つの方法はすべての引数を関数に渡し、最後の引数を返すことです。

#!/bin/bash

last() {
        if [[ $# -ne 0 ]] ; then
            shift $(expr $# - 1)
            echo "$1"
        #else
            #do something when no arguments
        fi
}

lastvar=$(last "$@")
echo $lastvar
echo "$@"

pax> ./qq.sh 1 2 3 a b
b
1 2 3 a b

実際にcareを使用しない場合、関数では必要ありませんが、他の引数を保持したくない状況を考えるのは困難ですそれらはすでに処理されています。その場合、私はそれらを順次処理するプロセス/シフト/プロセス/シフト/ ...メソッドを使用します。

ここではhave n'tがシーケンシャルメソッドに従っているため、それらを保持することを想定しています。このメソッドは、引数がない場合も処理し、「」を返します。コメントアウトされたelse句を挿入することで、その動作を簡単に調整できます。

2
paxdiablo

Tcshの場合:

set X = `echo $* | awk -F " " '{print $NF}'`
somecommand "$X"

これは、割り当てを除いて、ポータブルなソリューションになると確信しています。

2
Perfect64

bashの場合、 このコメント は非常にエレガントであると示唆しています。

echo "${@:$#}"
2
Tom Hale

以下は、現在の環境を変更せずにLASTを最後の引数に設定します:

LAST=$({
   shift $(($#-1))
   echo $1
})
echo $LAST

他の引数が不要になり、シフトできる場合は、次のように簡略化できます。

shift $(($#-1))
echo $1

以下の移植性の理由から:

shift $(($#-1));

次のものに置き換えることができます。

shift `expr $# - 1`

$()もバッククォートで置き換える:

LAST=`{
   shift \`expr $# - 1\`
   echo $1
}`
echo $LAST
1
Paweł Nadolski

evalを使用したソリューション:

last=$(eval "echo \$$#")

echo $last
1
Mikael S

これは私のコピー機能の一部です:

eval echo $(echo '$'"$#")

スクリプトで使用するには、次の操作を行います。

a=$(eval echo $(echo '$'"$#"))

説明(最もネストされた最初):

  1. $(echo '$'"$#")$[nr]を返します。ここで[nr]はパラメーターの数です。例えば。文字列$123(展開されていない)。
  2. echo $123は、評価時に123番目のパラメーターの値を返します。
  3. evalは、$123をパラメーターの値に展開するだけです。 last_arg。これは文字列として解釈され、返されます。

2015年半ばのBashで動作します。

1
Esavier

上記の回答を読んだ後、PGM.cppでg ++を実行して実行可能なイメージPGMを生成するQ&Dシェルスクリプト(shとbashで動作するはずです)を作成しました。コマンドラインの最後の引数はファイル名(.cppはオプション)であり、他のすべての引数はオプションであると想定しています。

#!/bin/sh
if [ $# -lt 1 ]
then
    echo "Usage: `basename $0` [opt] pgm runs g++ to compile pgm[.cpp] into pgm"
    exit 2
fi
OPT=
PGM=
# PGM is the last argument, all others are considered options
for F; do OPT="$OPT $PGM"; PGM=$F; done
DIR=`dirname $PGM`
PGM=`basename $PGM .cpp`
# put -o first so it can be overridden by -o specified in OPT
set -x
g++ -o $DIR/$PGM $OPT $DIR/$PGM.cpp
1
David E.
echo $argv[$#argv]

回答が短すぎて投稿できないため、テキストを追加する必要があります。編集するテキストをさらに追加する必要があります。

1
frank1rizzo

@AgileZebraの答え(および@starfryのコメント)が最も便利であることがわかりましたが、headsをスカラーに設定します。配列はおそらくより便利です。

heads=( "${@:1:$(($# - 1))}" )
tail=${@:${#@}}
1
EndlosSchleife

以下のスクリプトを試して最後の引数を見つけてください

 # cat arguments.sh
 #!/bin/bash
 if [ $# -eq 0 ]
 then
 echo "No Arguments supplied"
 else
 echo $* > .ags
 sed -e 's/ /\n/g' .ags | tac | head -n1 > .ga
 echo "Last Argument is: `cat .ga`"
 fi

出力:

 # ./arguments.sh
 No Arguments supplied

 # ./arguments.sh testing for the last argument value
 Last Argument is: value

ありがとう。

0
Ranjithkumar T
#! /bin/sh

next=$1
while [ -n "${next}" ] ; do
  last=$next
  shift
  next=$1
done

echo $last
0
Craig Trader

これを行うには、はるかに簡潔な方法があります。 bashスクリプトの引数を配列に入れると、要素の処理がはるかに簡単になります。以下のスクリプトは、常にスクリプトに渡された最後の引数を出力します。

  argArray=( "$@" )                        # Add all script arguments to argArray
  arrayLength=${#argArray[@]}              # Get the length of the array
  lastArg=$((arrayLength - 1))             # Arrays are zero based, so last arg is -1
  echo ${argArray[$lastArg]}

サンプル出力

$ ./lastarg.sh 1 2 buckle my shoe
shoe
0
tekbot

パラメーター展開を使用して(一致した先頭を削除):

args="$@"
last=${args##* }

最後まですべてを簡単に取得することもできます。

prelast=${args% *}
0
Jurij