Bashでの文字列インデックス付け

Bashでの文字列インデックス付け

sh / bashからインデックスとして文字列を参照する方法は?つまり、基本的に分かれています。

ファイル名から5文字を削除しようとしています。すべての名前の構造は name_nr_code です。英数字コードの5桁を削除しようとしています。name_nr_常に10文字です。

似たようなものがありますか?

for i in * ; do mv "$i" "$i"[:10] ; done

答え1

とても簡単です。

(しゃっくり)

for i in * ; do mv -- "$i" "${i:0:5}" ; done

望むより。

そしての説明高度なバッシュスクリプトガイド第10章 変数操作)、(追加のNOTEマニュアルのエラーを強調するためのインライン):

部分文字列の抽出

${string:position}

次の部分文字列を抽出します。$string存在する$position

パラメータが「*」または「@」の場合、$string位置パラメータはから始まり抽出されます$position

${string:position:length}

抜粋$length部分文字列の文字は次のようになります。$string存在する$position

NOTEパラメータ拡張に引用符がありません! echo任意のデータと一緒に使用しないでください。

stringZ=abcABC123ABCabc
#       0123456789.....
#       0-based indexing.

echo ${stringZ:0}                       # abcABC123ABCabc
echo ${stringZ:1}                       # bcABC123ABCabc
echo ${stringZ:7}                       # 23ABCabc 

echo ${stringZ:7:3}                     # 23A
                                        # Three characters of substring.


# Is it possible to index from the right end of the string?

echo ${stringZ:-4}                      # abcABC123ABCabc
# Defaults to full string, as in ${parameter:-default}.
# However . . . 

echo ${stringZ:(-4)}                    # Cabc
echo ${stringZ: -4}                     # Cabc
# Now, it works.
# Parentheses or added space "escape" the position parameter.

これ場所そして長さパラメータは「パラメータ化」できます。つまり、数値定数ではなく変数として表示されます。


引数が「*」または「@」の場合、最初から$string最大位置引数が抽出されます。$length$position

echo ${*:2}          # Echoes second and following positional parameters.
echo ${@:2}          # Same as above.

echo ${*:2:3}        # Echoes three positional parameters, starting at second.

NOTE: はexpr substrGNU 拡張です。

expr substr $string $position $length

抜粋$lengthの文字$string次から始まった$position

stringZ=abcABC123ABCabc
#       123456789......
#       1-based indexing.

echo `expr substr $stringZ 1 2`           # ab
echo `expr substr $stringZ 4 3`           # ABC

NOTE:これはecho冗長で信頼性がはるかに低いです。使用expr substr + "$string1" 1 2

NOTEexpr出力が0(または-0、00 ...)の場合、ゼロ以外の終了ステータスが返されます。


ところで。この本は公式Ubuntuリポジトリからabs-guide

答え2

POSIXではsh

  • "${var%?????}"$var最後の5文字を​​削除します(または文字が5文字未満の$var場合)。$var

  • "${var%"${var#??????????}"}"はい、最初の10文字です$var

  • "${var%_*}"$var(->)末尾から一致する最も短い文字列を削除します。_*$varfoo_bar_bazfoo_bar
  • "${var%%_*}":同じですが、最も短い一致(foo_bar_baz-> foo)ではなく、最も長い一致です。
  • 以下を取得したい場合foo_bar_:("${var%"${var##*_}"}"終わりの代わりに始めからパターンを見つけるのと同じ${var##pattern})。${var%%pattern}$var

そしてzsh

  • $var[1,-6]最初の文字から6番目の文字から最後の文字まで(最後の5文字を​​除くすべての文字)
  • $var[1,10]最初の10文字。

ksh、またはbashzsh

  • "${var:0:10}":の最初の10文字$var

またはbashzsh

  • "${var:0:-5}"$var:最後の5文字を​​除くすべての文字(設定されているが5文字未満の場合はエラーを表示してスクリプトを終了します。useなしで$var設定した場合も同様ですzsh)。

Bourneの互換性が必要な場合、sh安定して実行するのは難しいです。結果が改行で終わらないことを保証できる場合は、次のことができます。

first_10=`expr " $var" : ' \(.{1,10\}\)'` # beware the exit status
                                          # may be non-zero if the
                                          # result is 0 or 0000000000

all_but_last_5=`expr " $var" : ' \(.*\).\{5\}'`

また、長さ制限が適用されます$var(システムによって異なります)。

これらすべてのソリューションで$var有効な文字の一部を構成できないバイトを含めると、YMMVになります。

答え3

sh(私が知っている限り)文字列から部分文字列を取得する組み込みの方法はありませんが、bash次のことができます。

${i:0:10}

これにより、変数valueの最初の10文字が提供されますi

一般的な形式は${variable:offset:length}

答え4

forまず、ファイル名にループを使用しないでください。

まあ、このようなものが役に立ちます。

find ./ -type f | while read filename ;do
  newfilename=$(echo ${filename}|cut -c 1-10)
  mv ${filename} ${newfilename}
done

関連情報