Aufteilen der Zeichenfolge durch das erste Vorkommen eines Begrenzers

54

Ich habe eine Zeichenfolge im nächsten Format

id;some text here with possible ; inside

und wollen es nach dem ersten Auftreten der in 2 Zeichenketten aufteilen ;. So sollte es sein: idundsome text here with possible ; inside

Ich weiß, wie man den String teilt (zum Beispiel mit cut -d ';' -f1), aber er wird in mehr Teile geteilt, da ich ;im linken Teil bin .

Gakhov
quelle
Was möchten Sie nach dem Aufteilen der Zeichenfolge mit der "id" tun? Möchten Sie es einer Variablen zuweisen, ausdrucken usw.?
Daemon of Chaos
Ich werde 2 Variablen haben: idundstring
Gakhov

Antworten:

65

cut klingt nach einem geeigneten Werkzeug dafür:

bash-4.2$ s='id;some text here with possible ; inside'

bash-4.2$ id="$( cut -d ';' -f 1 <<< "$s" )"; echo "$id"
id

bash-4.2$ string="$( cut -d ';' -f 2- <<< "$s" )"; echo "$string"
some text here with possible ; inside

Ist readaber noch besser geeignet:

bash-4.2$ IFS=';' read -r id string <<< "$s"

bash-4.2$ echo "$id"
id

bash-4.2$ echo "$string"
some text here with possible ; inside
Mann bei der Arbeit
quelle
3
Toll! Es wirkt wie ein Zauber! Ich werde das auswählen, readda ich es benutze bash. Vielen Dank an @manatwork!
Gakhov
Der cutAnsatz funktioniert nur, wenn "$ s" keine Zeilenumbrüche enthält. read befindet sich in einer beliebigen Bourne-ähnlichen Shell. <<< ist in rc, zsh und den neuesten Versionen von bash und ksh93 und ist diejenige, die nicht Standard ist.
Stéphane Chazelas
Ups, Sie haben recht @StephaneChazelas. Mein Geist war -aaus irgendeinem Grunde , wenn erwähnen bash‚s read. (Offensichtlich
nutzlos
Ich habe vergessen zu erwähnen, dass der Leseansatz nicht funktioniert, wenn $ s auch Zeilenumbrüche enthält. Ich habe meine eigene Antwort hinzugefügt.
Stéphane Chazelas
1
Ich möchte den Hinter Strich in betonen -f 2-in dem string="$( cut -d ';' -f 2- <<< "$s" )"; echo "$string"Befehl. Dies ist, was den Rest der Begrenzer in der Zeichenfolge für den Ausdruck ignoriert. Nicht offensichtlich, wenn man sich die Manpage voncut
Steen am
17

Mit jedem Standard-Sh (einschließlich Bash):

sep=';'
case $s in
  (*"$sep"*)
    before=${s%%"$sep"*}
    after=${s#*"$sep"}
    ;;
  (*)
    before=$s
    after=
    ;;
esac

readbasierte Lösungen funktionieren für einzelne Zeichen (und bei einigen Shells auch für $sepEinzelbyte- Werte), $sdie keine Leerzeichen, Tabulatoren oder Zeilenumbrüche enthalten und nur dann, wenn sie keine Zeilenumbrüche enthalten.

cutbasierte Lösungen funktionieren nur, wenn $ssie keine Zeilenumbrüche enthalten.

sedEs könnten Lösungen entwickelt werden, die alle $sepEckfälle mit einem beliebigen Wert von abdecken, aber es lohnt sich nicht, so weit zu gehen, wenn die Shell dafür eine integrierte Unterstützung bietet.

Stéphane Chazelas
quelle
6

Wie Sie bereits erwähnt haben, möchten Sie die Werte id und string zuweisen

Weisen Sie Ihr Muster zunächst einer Variablen zu (z. B. str).

    str='id;some text here with possible ; inside'
    id=${str%%;} 
    string=${str#;}

Jetzt haben Sie Ihre Werte in entsprechenden Variablen

user1678213
quelle
Wenn Sie Ihr Muster von einem Befehl erhalten, verwenden Sie set - some_command, dann wird Ihr Muster in $ 1 gespeichert und verwenden Sie den obigen Code mit 1 anstelle von str
user1678213 31.10.12
Wie unterscheidet sich diese Antwort von @StephaneChazelas?
Bernhard
4

Zusätzlich zu den anderen Lösungen können Sie Folgendes ausprobieren regex:

a="$(sed 's/;.*//' <<< "$s")"
b="$(sed 's/^[^;]*;//' <<< "$s")"

oder je nachdem, was Sie genau versuchen, können Sie verwenden

sed -r 's/^([^;]*);(.*)/\1 ADD THIS TEXT BETWEEN YOUR STRINGS \2/'

wo \1und \2enthalten Sie die beiden gewünschten Teilzeichenfolgen.

tojrobinson
quelle
1

Lösung in Standard-Bash:

    text='id;some text here with possible ; inside'
    text2=${text#*;}
    text1=${text%"$text2"}

    echo $text1
    #=> id;
    echo $text2
    #=> some text here with possible ; insideDD
ethaning
quelle