Entfernen Sie die Zeichen rechts vom ersten Leerzeichen in Bash

8
2492  some string continues here

Ich möchte dies in konvertieren

2492

in Bash. Wie würde ich das machen?

Das fühlt sich eng an, funktioniert aber nicht:

var="2492  some string continues here  "
echo ${var%[[:space:]]*}
Joshua Soileau
quelle
Wird es niemals führende Leerzeichen geben?
Alexander
Wenn Sie fragen, wie es in Bash gemacht werden soll, sollten Sie Bash wahrscheinlich nicht verwenden, um es zu machen. Benutze Perl oder so.
Ben

Antworten:

14

Weil Sie mehrere Leerzeichen verwenden möchten

${var%%[[:space:]]*}
# ...^^

um den längsten nachfolgenden Teilstring zu entfernen , der mit einem Leerzeichen beginnt

Mit nur einem %Zeichen entfernen Sie die kürzeste Folge eines Leerzeichens, gefolgt von null oder mehr Zeichen. Dies ist nur das letzte Leerzeichen in der Zeichenfolge.

$ echo ">$var<"; echo ">${var%[[:space:]]*}<"; echo ">${var%%[[:space:]]*}<"
>2492  some string continues here  <
>2492  some string continues here <
>2492<

Wenn Sie nur nach dem ersten Wort suchen , können Sie dies tun:

read -r word rest_of_string <<<"$var"
echo "I have: $word"

Dies kümmert sich um führende Leerzeichen, vorausgesetzt, Sie haben die IFS-Variable nicht geändert.

Glenn Jackman
quelle
Wie wäre es, wenn die Zeichenfolge ein führendes Leerzeichen enthält? `2492 hier geht eine Saite weiter`
Joshua Soileau
Dadurch werden alle Zeichen entfernt.
Glenn Jackman
[:space:]Die Zeichenklasse umfasst Leerzeichen, Tabulatoren, CR, NL usw. Es ist also ein Allheilmittel für jedes Leerzeichen.
Glenn Jackman
1
a=($var); echo "${a[0]}"funktioniert auch für den Zugriff auf das erste Wort bei führenden Leerzeichen.
Digitales Trauma
Sie setzen den Wert der Dateinamenerweiterung sowie der set -f
Wortaufteilung aus
3

Es gibt die einfache Lösung, %%( ${var%% *}) anstelle von %( ${var% *}) zu verwenden. Dadurch wird *nach einem anfänglichen Leerzeichen alles ( ) entfernt.

$ var='2492  some string continues here'
$ echo "${var%% *}"
2492

Dies schlägt jedoch fehl, wenn die Zeichenfolge in var führende Leerzeichen enthält. Es ist möglich, die führenden Leerzeichen zu entfernen mit:

$ var=$' \t 2492  some string continues here  '
$ var="${var#"${var%%[![:space:]]*}"}"
$ echo "$var"
2492  some string continues here  
$ echo "${var%%[[:space:]]*}"
2492

Dies funktioniert auch dann, wenn die Leerzeichen Leerzeichen-Registerkarten NL oder CR sind.


Regex

Eine robustere Lösung ist möglicherweise die Verwendung eines regulären Ausdrucks:

$ var=$' \t 2492  some string continues here  '
$ regex='^[[:space:]]*([^[:space:]]+)'
$ [[ $var =~ $regex ]] && var=${BASH_REMATCH[1]}
$ echo "$var"
2492
Isaac
quelle
1
Ich denke, das ist das erste Mal, dass ich jemanden sehe, der reguläre Ausdrücke als "robuster" bezeichnet ;-)
Kusalananda
2

Sie können auch das einfache Werkzeug verwenden cut, das Zeichenfolgen basierend auf einem Trennzeichen schneidet:

echo "$mystring" | cut -d' ' -f 1 

Wo :

  • -d' ' Setzt das Trennzeichen auf ein Leerzeichen
  • -f 1 gibt das erste Feld an (basierend auf dem Trennzeichen)
Ikaros
quelle
Ich mag diesen. Keine regulären Ausdrücke, keine Programmiersprachen.
Gronostaj
1

Sie können die native Shell-String-Manipulation verwenden:

TEST="test  1234 foo"
SPLIT_VAR=${TEST/ */ }

Es ersetzt das erste Muster, das mit "*" übereinstimmt (ein Leerzeichen, dann irgendetwas), und ersetzt es durch "" (ein Leerzeichen). Sie behalten also das erste Wort und das erste Leerzeichen.

Weitere Informationen zur Verwendung der Zeichenfolgenmanipulation finden Sie unter http://www.tldp.org/LDP/abs/html/string-manipulation.html .

Und als Randnotiz, es funktioniert auch weniger entwickelte Shell (getestet auf der Ash-Implementierung von Busybox).

Bärenbart
quelle
0

Um nur Bash- und integrierte Befehle zu verwenden, können Sie IFS ( Internal Field Seperator ) und Arrays verwenden

set -f                # To prevent filename globbing when creating the array, as pointed out by Kusalananda in the comments
array=(2492 some string continues here)
set +f                # enable it again
IFS=" "
echo "${array[0]}"
unset IFS
Robert Riedl
quelle
Versuchen Sie das mit einer Zeichenfolge, die z *.
Kusalananda
@Kusalananda versuchte es mit array=(*2492* *some * *string continues* here)- funktioniert immer noch
Robert Riedl
Fügen Sie nun eine Datei in das aktuelle Verzeichnis ein, die beispielsweise 2492den Namen enthält myfile-2492.txt, und führen Sie sie erneut aus.
Kusalananda
1
@Kusalananda oh wow, warum passiert das?
Robert Riedl
1
@Kusalananda, ich denke ich muss mit beginnen set -fund enden mit set +f?
Robert Riedl
0

Wenn Ihnen ein externer Anruf nichts ausmacht, verwenden Sie awk oder sed:

$ string="first second third fourth"
$ echo "${string}" | awk '{print $1}' # will work even with tabs
first
$ echo "${string}" | sed -e "s/ .*$//" # will fail on leading whitespace
first
anonym bei der Arbeit
quelle
Siehe auch
Kusalananda
Zitiert meine Saiten, danke, dass Sie @Kusalananda gefangen haben
anonym bei der Arbeit