Suppose I have the string 1:2:3:4:5
and I want to get its last field (5
in this case). How do I do that using Bash? I tried cut
, but I don't know how to specify the last field with -f
.
17 に答える
文字列演算子を使用できます:
$ foo=1:2:3:4:5
$ echo ${foo##*:}
5
これにより、前面から「:」まですべてが貪欲にトリミングされます。
${foo <-- from variable foo
## <-- greedy front trim
* <-- matches anything
: <-- until the last ':'
}
別の方法は、前後を逆にすることですcut
:
$ echo ab:cd:ef | rev | cut -d: -f1 | rev
ef
これにより、最後の1つのフィールド、または最後から番号が付けられた任意の範囲のフィールドを非常に簡単に取得できます。
カットを使用して最後のフィールドを取得することは困難ですが、ここにawkとperlのいくつかの解決策があります
echo 1:2:3:4:5 | awk -F: '{print $NF}'
echo 1:2:3:4:5 | perl -F: -wane 'print $F[-1]'
かなり単純な使用法(たとえば、区切り文字のエスケープなし)を想定すると、grepを使用できます。
$ echo "1:2:3:4:5" | grep -oE "[^:]+$"
5
内訳-行末($)の区切り文字([^:])以外のすべての文字を検索します。-oは一致する部分のみを印刷します。
一方通行:
var1="1:2:3:4:5"
var2=${var1##*:}
もう1つは、配列を使用します。
var1="1:2:3:4:5"
saveIFS=$IFS
IFS=":"
var2=($var1)
IFS=$saveIFS
var2=${var2[@]: -1}
配列を持つさらに別の:
var1="1:2:3:4:5"
saveIFS=$IFS
IFS=":"
var2=($var1)
IFS=$saveIFS
count=${#var2[@]}
var2=${var2[$count-1]}
Bash(バージョン> = 3.2)正規表現の使用:
var1="1:2:3:4:5"
[[ $var1 =~ :([^:]*)$ ]]
var2=${BASH_REMATCH[1]}
あなたが使用したい場合は、このようなものを試すことができますcut
:
echo "1:2:3:4:5" | cut -d ":" -f5
次のように試してみることもできますgrep
:
echo " 1:2:3:4:5" | grep -o '[^:]*$'
$ echo "a b c d e" | tr ' ' '\n' | tail -1
e
区切り文字を改行に変換し、最後のエントリを。で選択するだけtail -1
です。
使用sed
:
$ echo '1:2:3:4:5' | sed 's/.*://' # => 5
$ echo '' | sed 's/.*://' # => (empty)
$ echo ':' | sed 's/.*://' # => (empty)
$ echo ':b' | sed 's/.*://' # => b
$ echo '::c' | sed 's/.*://' # => c
$ echo 'a' | sed 's/.*://' # => a
$ echo 'a:' | sed 's/.*://' # => (empty)
$ echo 'a:b' | sed 's/.*://' # => b
$ echo 'a::c' | sed 's/.*://' # => c
ここには多くの良い答えがありますが、それでも私はbasenameを使用してこれを共有したいと思います:
basename $(echo "a:b:c:d:e" | tr ':' '/')
ただし、文字列にすでに「/」が含まれている場合は失敗します。スラッシュ/が区切り文字である場合は、basenameを使用する必要があります(使用する必要があります)。
これは最良の答えではありませんが、bashコマンドを使用して創造性を発揮する方法を示しています。
Bashを使用します。
$ var1="1:2:3:4:0"
$ IFS=":"
$ set -- $var1
$ eval echo \$${#}
0
echo "a:b:c:d:e"|xargs -d : -n1|tail -1
最初にxargsを使用して、「:」を使用して分割します。-n1は、すべての行に1つの部分しかないことを意味します。次に、最後の部分をpringします。
組み込みの読み取りを使用したソリューション:
IFS=':' read -a fields <<< "1:2:3:4:5"
echo "${fields[4]}"
または、より一般的にするには:
echo "${fields[-1]}" # prints the last item
for x in `echo $str | tr ";" "\n"`; do echo $x; done
Pythonに慣れている人にとっては、https://github.com/Russell91/pythonpyがこの問題を解決するための良い選択です。
$ echo "a:b:c:d:e" | py -x 'x.split(":")[-1]'
pythonpyヘルプから:-x treat each row of stdin as x
。
このツールを使用すると、入力に適用されるPythonコードを簡単に記述できます。
編集(2020年12月):Pythonpyはオンラインではなくなりました。別の方法は次のとおりです。
$ echo "a:b:c:d:e" | python -c 'import sys; sys.stdout.write(sys.stdin.read().split(":")[-1])'
より多くのボイラープレートコード(つまりsys.stdout.read/write
)が含まれていますが、Pythonのstdライブラリのみが必要です。
での正規表現の一致sed
は貪欲であり(常に最後の発生になります)、ここで有利に使用できます。
$ foo=1:2:3:4:5
$ echo ${foo} | sed "s/.*://"
5
Pythonが好きで、パッケージをインストールするオプションがある場合は、このpythonユーティリティを使用できます。
# install pythonp
pythonp -m pip install pythonp
echo "1:2:3:4:5" | pythonp "l.split(':')[-1]"
5