Buat indeks string dalam bash


14

Bagaimana saya bisa merujuk ke string dengan indeks di sh / bash? Artinya, pada dasarnya membelahnya.

Saya mencoba menghapus 5 karakter nama file. Semua nama memiliki struktur: name_nr_code. Saya mencoba untuk menghapus bit kode 5 alfanumerik. name_nr_selalu 10 karakter.

Apakah ada sesuatu seperti;

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


5
Mengapa bashmemberi tag jika Anda meminta shsolusi?
Stéphane Chazelas

Jawaban:


14

Sesederhana ini.

(pesta)

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

Voila.

Dan penjelasan dari Advanced Bash-Scripting Guide ( Bab 10. Memanipulasi Variabel ) , (dengan tambahan NOTEsebaris untuk menyoroti kesalahan dalam manual itu):

Ekstraksi Substring

${string:position}

Ekstrak substring dari $stringpada $position.

Jika $stringparameternya "*" atau "@", maka ini mengekstrak parameter posisi, mulai dari $position.

${string:position:length}

Ekstrak $lengthkarakter substring dari $stringpada $position.

NOTEkutipan yang hilang di sekitar ekspansi parameter! echotidak boleh digunakan untuk data sewenang-wenang.

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.

The posisi dan panjang argumen dapat "diparameterisasi," yaitu, direpresentasikan sebagai variabel, daripada sebagai konstan numerik.


Jika $stringparameternya "*" atau "@", maka ini akan mengekstrak maksimum $lengthparameter posisi, mulai dari $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 substradalah ekstensi GNU.

expr substr $string $position $length

Ekstrak $lengthkarakter $stringmulai dari $position.

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

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

NOTE: Itu echoberlebihan dan membuatnya bahkan kurang dapat diandalkan. Gunakan expr substr + "$string1" 1 2.

NOTE: exprakan kembali dengan status keluar non-nol jika outputnya 0 (atau -0, 00 ...).


BTW. Buku ini hadir dalam repositori resmi Ubuntu sebagai abs-guide.


Mengatakan "posisi" sedikit menyesatkan karena sebenarnya merupakan offset, yang berarti ${var:1}tidak mengembalikan nilai dari var"posisi pertama", tetapi sebenarnya dari posisi kedua.
Kusalananda

Itu benar, tetapi selama Anda tidak setuju akan ada posisi ke-nol. Tidak masalah dengan saya.

9

Dalam POSIX sh,

  • "${var%?????}"adalah $vardilucuti dari 5 karakter membuntuti terakhir (atau $varjika $varmengandung kurang dari 5 karakter)

  • "${var%"${var#??????????}"}"adalah 10 karakter pertama dari $var.

  • "${var%_*}"adalah $vardilucuti dari string terpendek yang cocok _*pada akhir $var( foo_bar_baz-> foo_bar).
  • "${var%%_*}": pertandingan yang sama tetapi yang terpanjang dan bukan yang terpendek ( foo_bar_baz-> foo).
  • jika Anda ingin mendapatkan foo_bar_: "${var%"${var##*_}"}"( ${var##pattern}sama seperti ${var%%pattern}tetapi mencari pola di awal, $varbukan di akhir).

Dengan zsh:

  • $var[1,-6] untuk karakter pertama ke 6 dari akhir (jadi semuanya kecuali 5 terakhir).
  • $var[1,10] untuk 10 karakter pertama.

Dengan ksh, bashatau zsh:

  • "${var:0:10}": 10 karakter pertama dari $var

Dengan bashatau zsh:

  • "${var:0:-5}": all kecuali 5 karakter terakhir (memberikan kesalahan dan keluar dari skrip jika $vardiset tetapi berisi kurang dari 5 karakter, juga saat $vartidak diatur dengan zsh).

Jika Anda memerlukan shkompatibilitas Bourne , sangat sulit dilakukan dengan andal. Jika Anda dapat menjamin hasilnya tidak akan berakhir dalam karakter baris baru yang dapat Anda lakukan:

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\}'`

Anda juga akan memiliki batas panjang $var(bervariasi antar sistem).

Dalam semua solusi itu, jika $varberisi byte yang tidak dapat membentuk bagian dari karakter yang valid, YMMV.


Ya, mereka benar-benar menghasilkan sintaks yang jelek untuk di dalam kawat gigi itu.
kucing

2

shtidak menyediakan cara bawaan untuk mengeluarkan substring dari string (sejauh yang saya bisa lihat), tetapi dengan bashAnda dapat melakukannya

${i:0:10}

Ini akan memberi Anda sepuluh karakter pertama dari nilai variabel i.

Format umum adalah ${variable:offset:length}.


2

Sebagian besar cangkang mendukung beberapa jenis perluasan parameter yang dapat membantu Anda. Di bash, Anda bisa menggunakan

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

Di dash, offset tidak didukung, tetapi Anda dapat menggunakan pola awal dan akhir:

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

0

Pertama, jangan gunakan forloop untuk nama file.

Maka, sesuatu seperti ini akan membantu.

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

3
Mengapa buruk menggunakan fornama file?
choroba

Kutip variabel Anda dan gunakan printfuntuk menjadi lebih aman. ... dan read -r.
Kusalananda

3
forLingkaran OP baik-baik saja kecuali mungkin untuk yang hilang --. Saya dapat melihat setidaknya 10 bug dalam 4 baris kode Anda! banyak di antaranya praktik buruk yang terkenal seperti menganggap nama file adalah satu baris, gunakan gema, kutipan yang hilang
Stéphane Chazelas
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.