Sh/bashのインデックスで文字列を参照するにはどうすればよいですか?つまり、基本的に分割します。
ファイル名の5文字を削除しようとしています。すべての名前の構造は、name_nr_codeです。 5つの英数字コードビットを削除しようとしています。 name_nr_
は常に10文字です。
のようなものはありますか?
for i in * ; do mv "$i" "$i"[:10] ; done
このように単純です。
(バッシュ)
for i in * ; do mv -- "$i" "${i:0:5}" ; done
出来上がり。
Advanced Bash-Scripting Guide ( Chapter 10. Manipulating Variables )からの説明 NOTEsそのマニュアルのエラーを強調するためのインライン):
サブストリング抽出
${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.
positionおよびlength引数は、「パラメータ化」することができます。つまり、数値定数としてではなく、変数として表すことができます。
$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 substr
はGNU拡張です。
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
を使用してください。
NOTE:expr
は、出力が0(または-0、00 ...)の場合、ゼロ以外の終了ステータスで戻ります。
ところで。この本はabs-guide
として公式のUbuntuリポジトリにあります。
POSIX sh
では、
"${var%?????}"
は$var
から最後の5文字を取り除いたもの(または$var
に含まれる文字が5文字未満の場合は$var
)
"${var%"${var#??????????}"}"
は$var
の最初の10文字です。
"${var%_*}"
は、$var
の最後の_*
に一致する最短の文字列を取り除いた$var
です(foo_bar_baz
-> foo_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
、bash
またはzsh
の場合:
"${var:0:10}"
:$var
の最初の10文字bash
またはzsh
の場合:
"${var:0:-5}"
:最後の5文字を除くすべて($var
が設定されていて5文字未満の場合、$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。
sh
は、文字列から部分文字列を取得する組み込みの方法を提供していません(私の知る限り)が、bash
を使用すると、
${i:0:10}
これにより、変数i
の値の最初の10文字が得られます。
一般的な形式は${variable:offset:length}
。
ほとんどのシェルは、あなたを助けることができるある種のパラメータ拡張をサポートします。 bashでは、
substr=${string:4:5} # start at position 4, length 5.
dash
では、オフセットはサポートされていませんが、先頭と末尾のパターンを使用できます。
remove_first3=${string#???}
remove_last2=${string%??}
まず、ファイル名にfor
ループを使用しないでください。
次に、このようなものが役立つはずです。
find ./ -type f | while read filename ;do
newfilename=$(echo ${filename}|cut -c 1-10)
mv ${filename} ${newfilename}
done