web-dev-qa-db-ja.com

bashで文字列にインデックスを付ける

Sh/bashのインデックスで文字列を参照するにはどうすればよいですか?つまり、基本的に分割します。

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

のようなものはありますか?

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

15
Pierre B

このように単純です。

(バッシュ)

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

出来上がり。

Advanced Bash-Scripting GuideChapter 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.

NOTEexpr 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を使用してください。

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


ところで。この本はabs-guideとして公式のUbuntuリポジトリにあります。

16
user147505

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文字。

kshbashまたはzshの場合:

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

bashまたはzshの場合:

  • "${var:0:-5}":最後の5文字を​​除くすべて($varが設定されていて5文字未満の場合、$varzsh)。

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。

9

shは、文字列から部分文字列を取得する組み込みの方法を提供していません(私の知る限り)が、bashを使用すると、

${i:0:10}

これにより、変数iの値の最初の10文字が得られます。

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

2
Kusalananda

ほとんどのシェルは、あなたを助けることができるある種のパラメータ拡張をサポートします。 bashでは、

substr=${string:4:5} # start at position 4, length 5.

dashでは、オフセットはサポートされていませんが、先頭と末尾のパターンを使用できます。

remove_first3=${string#???}
remove_last2=${string%??}
2
choroba

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

次に、このようなものが役立つはずです。

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