回答:
cut
with _
をフィールド区切り文字として使用し、目的のフィールドを取得します。
A="$(cut -d'_' -f2 <<<'one_two_three_four_five')"
B="$(cut -d'_' -f4 <<<'one_two_three_four_five')"
echo
Here文字列の代わりにand pipeを使用することもできます:
A="$(echo 'one_two_three_four_five' | cut -d'_' -f2)"
B="$(echo 'one_two_three_four_five' | cut -d'_' -f4)"
例:
$ s='one_two_three_four_five'
$ A="$(cut -d'_' -f2 <<<"$s")"
$ echo "$A"
two
$ B="$(cut -d'_' -f4 <<<"$s")"
$ echo "$B"
four
$ echo $FILE
my_user/my_folder/file.csv
$ A="$(cut -d'/' -f2 <<<"$FILE")"
$ echo $A
[file]*
。
echo "${s##*_}"
POSIX shコンストラクトのみを使用すると、パラメーター置換コンストラクトを使用して、一度に1つの区切り文字を解析できます。このコードは、必要な数のフィールドがあることを前提としていることに注意してください。そうでない場合、最後のフィールドが繰り返されます。
string='one_two_three_four_five'
remainder="$string"
first="${remainder%%_*}"; remainder="${remainder#*_}"
second="${remainder%%_*}"; remainder="${remainder#*_}"
third="${remainder%%_*}"; remainder="${remainder#*_}"
fourth="${remainder%%_*}"; remainder="${remainder#*_}"
または、ワイルドカード拡張を無効にしIFS
て、区切り文字に設定した引用符なしのパラメーター置換を使用できます(これは、区切り文字が単一の非空白文字である場合、または空白シーケンスが区切り文字である場合にのみ機能します)。
string='one_two_three_four_five'
set -f; IFS='_'
set -- $string
second=$2; fourth=$4
set +f; unset IFS
これにより、位置パラメータが破壊されます。関数でこれを行うと、関数の定位置パラメーターのみが影響を受けます。
さらに別のアプローチは、read
組み込みを使用することです。
IFS=_ read -r first second third fourth trail <<'EOF'
one_two_three_four_five
EOF
unset IFS
戻りませんIFS
。その後、誰かがOldIFS="$IFS"
OldIFS内でnull値を持つ場合。また、IFSの以前の値がデフォルトであると想定しています。唯一の正しい解決策はold="$IFS"
、IFS = "$ old"で保存して後で復元することです。または...サブシェルを使用します(...)
。または、さらに良いことに、私の答えを読んでください。
unset IFS
はIFS
デフォルト値に復元しませんが、フィールド分割をデフォルトの効果に戻します。はい、それは制限ですが、実際には通常許容されます。サブシェルの問題は、そこからデータを取得する必要があることです。最後に状態を変更しないソリューションを示しread
ます。(POSIXシェルで動作しますが、IIRCはヒアread
ドキュメントによりサブシェルで実行されるため、Bourneシェルでは動作<<<
しません。)as in your answerは、ksh / bash / zshでのみ動作するバリアントです。
user/my_folder/[this_is_my_file]*
ますか?私は次の手順を実行したときに、私は得ることである[this_is_my_file]*
/
。
awk
答えを見たかったので、ここに一つあります:
A=$(awk -F_ '{print $2}' <<< 'one_two_three_four_five')
B=$(awk -F_ '{print $4}' <<< 'one_two_three_four_five')
awk -F_ '{print $NF}' <<< 'one_two_3_4_five'
最も簡単な方法(<<のシェルの場合)は次のとおりです。
IFS='_' read -r a second a fourth a <<<"$string"
1つのシェルが文句を言うの$a
ではなく、一時変数を使用します$_
。
完全なスクリプトの場合:
string='one_two_three_four_five'
IFS='_' read -r a second a fourth a <<<"$string"
echo "$second $fourth"
IFSの変更なし、set -f
(パス名の展開)の問題なし位置パラメーター( "$ @")の変更なし。
IFSまたはを変更せずにすべてのシェル(はい、すべてのPOSIXを含む)に移植可能なソリューションのset -f
場合、(もう少し複雑な)ヒアドキュメントの同等物を使用します。
string='one_two_three_four_five'
IFS='_' read -r a second a fourth a <<-_EOF_
$string
_EOF_
echo "$second $fourth"
このソリューション(here-docとの使用により<<<
、後続の改行がすべて削除されます。
また、これは「1ライナー」可変コンテンツに合わせて設計されています。
マルチライナーのソリューションは可能ですが、より複雑な構成が必要です。
bashバージョン4.4では、非常に簡単なソリューションが可能です。
readarray -d _ -t arr <<<"$string"
echo "array ${arr[1]} ${arr[3]}" # array numbers are zero based.
多くのPOSIXシェルには配列がないため、POSIXシェルに相当するものはありません。
配列を持つシェルの場合は、次のように簡単です
(attsh、lksh、mksh、ksh、およびbashで動作確認済み)
set -f; IFS=_; arr=($string)
しかし、変数とオプションを保持およびリセットするための追加の配管がたくさんあります:
string='one_* *_three_four_five'
case $- in
*f*) noglobset=true; ;;
*) noglobset=false;;
esac
oldIFS="$IFS"
set -f; IFS=_; arr=($string)
if $noglobset; then set -f; else set +f; fi
echo "two=${arr[1]} four=${arr[3]}"
zshでは、配列は1から始まり、デフォルトでは文字列を分割しません。
したがって、これをzshで機能させるには、いくつかの変更を行う必要があります。
read
OPが長い文字列から76番目と127番目の要素を抽出したくない限り、使用するソリューションは単純です
readarray
そのような状況では使いやすいかもしれません。
zsh
あなたは(上の文字列を分割でき_
配列に):
elements=(${(s:_:)string})
そして、配列インデックスを介して各要素にアクセスします:
print -r ${elements[4]}
zsh
(ksh
/ とは異なりbash
)配列のインデックスは1から始まることに注意してください。
set -f
最初のソリューションに警告を追加することを忘れないでください。... *
多分アスタリスク?
set -f
ですか?read
/ を使用していませんIFS
。以下のような文字列で私の解決策を試してみてください*_*_*
または何...
別のawkの例。理解しやすい。
A=\`echo one_two_three_four_five | awk -F_ '{print $1}'\`
B=\`echo one_two_three_four_five | awk -F_ '{print $2}'\`
C=\`echo one_two_three_four_five | awk -F_ '{print $3}'\`
... and so on...
変数でも使用できます。
たとえば、
this_str = "one_two_three_four_five" とすると
、次のように動作します
。A = `echo $ {this_str} | awk -F_ '{print $ 1}' `
B =` echo $ {this_str} | awk -F_ '{print $ 2}' `
C =` echo $ {this_str} | awk -F_ '{print $ 3}' `
...など...