Indizieren Sie eine Zeichenfolge in Bash


14

Wie kann ich in sh / bash nach Index auf einen String verweisen? Das heißt, im Grunde es zu teilen.

Ich versuche, 5 Zeichen eines Dateinamens zu entfernen. Alle Namen haben die Struktur: name_nr_code. Ich versuche, das 5 alphanumerische Codebit zu entfernen. name_nr_ist immer 10 Zeichen.

Gibt es so etwas?

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


5
Warum das bashTag, wenn Sie nach einer shLösung fragen ?
— Stéphane Chazelas

Antworten:


14

So einfach ist das.

(Bash)

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

Voila.

Und eine Erklärung aus dem Advanced Bash-Scripting Guide ( Kapitel 10. Manipulieren von Variablen ) (mit zusätzlichen NOTEs inline, um die Fehler in diesem Handbuch hervorzuheben):

Teilstrangextraktion

${string:position}

Extrahiert einen Teilstring aus $stringat $position.

Wenn der $stringParameter "*" oder "@" ist, werden die Positionsparameter extrahiert, beginnend mit $position.

${string:position:length}

Extrahiert $lengthZeichen des Teilstrings aus $stringat $position.

NOTEfehlende Anführungszeichen um Parametererweiterungen! echosollte nicht für beliebige Daten verwendet werden.

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.

Die Position und Länge Argumente können „parametrisiert“ sein , die, dargestellt als eine Variable, und nicht als eine numerische Konstante ist .


Wenn der $stringParameter "*" oder "@" ist, extrahiert dies ein Maximum von $lengthPositionsparametern, beginnend mit $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 substrist eine GNU-Erweiterung.

expr substr $string $position $length

Extrahiert $lengthZeichen $stringab $position.

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

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

NOTE: Das echoist überflüssig und macht es noch weniger zuverlässig. Verwenden Sie expr substr + "$string1" 1 2.

NOTE: exprwird mit einem Ausgangsstatus ungleich Null zurückgegeben, wenn der Ausgang 0 (oder -0, 00 ...) ist.


Übrigens. Das Buch ist im offiziellen Ubuntu-Repository als vorhanden abs-guide.


"Position" zu sagen ist leicht irreführend, da es sich tatsächlich um einen Offset handelt, was bedeutet, dass ${var:1}nicht der Wert von var"1. Position", sondern der Wert von "2. Position" zurückgegeben wird.
— Kusalananda

Das stimmt, aber solange Sie nicht zustimmen, kann es eine nullte Position geben. Welches ist in Ordnung mit mir.

9

In POSIX sh,

  • "${var%?????}"wird $varvon den letzten 5 nachgestellten Zeichen befreit (oder $varwenn $varweniger als 5 Zeichen enthalten sind)

  • "${var%"${var#??????????}"}"sind die ersten 10 Zeichen von $var.

  • "${var%_*}"wird $varvon der kürzesten Zeichenfolge befreit, die _*am Ende von $var( foo_bar_baz-> foo_bar) übereinstimmt .
  • "${var%%_*}": Gleiche, aber längste Übereinstimmung anstelle der kürzesten Übereinstimmung ( foo_bar_baz-> foo).
  • wenn du bekommen wolltest foo_bar_: "${var%"${var##*_}"}"( ${var##pattern}ist das selbe wie ${var%%pattern}aber suche das muster am anfang $varstatt am ende).

Mit zsh:

  • $var[1,-6] für das erste Zeichen bis zum 6. vom Ende (also alle bis auf die letzten 5).
  • $var[1,10] für die ersten 10 Zeichen.

Mit ksh, bashoder zsh:

  • "${var:0:10}": die ersten 10 Zeichen von $var

Mit bashoder zsh:

  • "${var:0:-5}": alle bis auf die letzten 5 Zeichen (gibt einen Fehler aus und beendet das Skript, wenn $varfestgelegt, enthält aber weniger als 5 Zeichen, auch wenn $varnicht mit festgelegt zsh).

Wenn Sie Bourne- shKompatibilität benötigen , ist es sehr schwierig, dies zuverlässig zu tun. Wenn Sie sicherstellen können, dass das Ergebnis nicht in Zeilenumbrüchen endet, können Sie Folgendes tun:

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

Sie können auch die Länge von $var(je nach System unterschiedlich) begrenzen .

Wenn in all diesen Lösungen $varBytes enthalten sind, die nicht Teil gültiger Zeichen sind, wird YMMV verwendet.


Meine Güte, sie haben sich wirklich eine hässliche Syntax für diese Klammern ausgedacht.
— Katze

2

shbietet keine eingebaute Möglichkeit, einen Teilstring aus einem String zu holen (soweit ich sehen kann), aber bashSie können es tun

${i:0:10}

Dadurch erhalten Sie die ersten zehn Zeichen des Werts der Variablen i.

Das allgemeine Format ist ${variable:offset:length}.


2

Die meisten Shells unterstützen eine Art Parametererweiterung, die Ihnen helfen kann. In Bash können Sie verwenden

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

In dashwerden Offsets nicht unterstützt, Sie können jedoch führende und nachfolgende Muster verwenden:

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

0

Verwenden Sie zunächst keine forSchleife für Dateinamen.

Dann sollte so etwas helfen.

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

3
Warum ist es schlecht, formit Dateinamen zu verwenden?
— Choroba

Zitieren Sie Ihre Variablen und verwenden Sie printf, um sicherer zu sein. ... und read -r.
— Kusalananda

3
Die OP- forSchleife war in Ordnung, bis auf die fehlenden --. Ich kann mindestens 10 Bugs in Ihren 4 Codezeilen sehen! Viele der bekannten schlechten Praktiken wie die Annahme, dass Dateinamen einzeilig sind, verwenden Echo, fehlende Anführungszeichen
— Stéphane Chazelas
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.