Respuestas:
Awk es una buena opción si tienes que lidiar con espacios en blanco finales porque se encargará de ti:
echo " word1 word2 " | awk '{print $1;}' # Prints "word1"
Sin embargo, Cut no se ocupará de esto:
echo " word1 word2 " | cut -f 1 -d " " # Prints nothing/whitespace
'cortar' aquí no imprime nada / espacio en blanco, porque lo primero antes de un espacio era otro espacio.
-F","
para anular el separador de campo predeterminado (un espacio) con una coma.
No es necesario utilizar comandos externos. Bash en sí mismo puede hacer el trabajo. Suponiendo "word1 word2" que obtuvo de algún lugar y se almacenó en una variable, por ejemplo
$ string="word1 word2"
$ set -- $string
$ echo $1
word1
$ echo $2
word2
ahora puede asignar $ 1, o $ 2, etc. a otra variable si lo desea.
stdin
. @Matt M. --
significa stdin
, por lo que $string
se pasa como stdin
. stdin
está separada por un espacio en blanco en argumentos $1
, $2
, $3
, etc. - al igual que cuando un Bash Evalúa programa argumentos (por ejemplo, comprobación $1
, $2
etc.), este enfoque se aprovecha de la tendencia de la cáscara para dividir el stdin
en argumentos de forma automática, eliminando la necesidad de awk
o cut
.
set
establece los argumentos del shell.
word1=$(IFS=" " ; set -- $string ; echo $1)
Configure IFS para reconocer correctamente el espacio entre las palabras. Envuelva entre paréntesis para evitar golpear el contenido original de $ 1.
string="*"
. Sorpresa.
Creo que una forma eficiente es el uso de matrices bash:
array=( $string ) # do not use quotes in order to allow word expansion
echo ${array[0]} # You can retrieve any word. Index runs from 0 to length-1
Además, puede leer directamente matrices en una tubería:
echo "word1 word2" | while read -a array; do echo "${array[0]}" ; done
echo " word1 word2 " | { read -a array ; echo ${array[0]} ; }
string="*"
. Sorpresa.
while
sintaxis para recuperar cada primera palabra en cada línea. De lo contrario, utilice el enfoque Boontawee Home. Además, tenga en cuenta que echo "${array[0]}"
se ha citado para evitar la expansión como lo notó gniourf-gniourf.
echo "word1 word2 word3" | { read first rest ; echo $first ; }
Esto tiene la ventaja de que no utiliza comandos externos y deja intactas las variables $ 1, $ 2, etc.
$1, $2, …
intactas es una característica extremadamente útil para escribir guiones!
Si está seguro de que no hay espacios iniciales, puede usar la sustitución de parámetros bash:
$ string="word1 word2"
$ echo ${string/%\ */}
word1
Cuidado con escapar del espacio único. Vea aquí para más ejemplos de patrones de sustitución. Si tiene bash> 3.0, también puede usar la coincidencia de expresiones regulares para hacer frente a los espacios iniciales: consulte aquí :
$ string=" word1 word2"
$ [[ ${string} =~ \ *([^\ ]*) ]]
$ echo ${BASH_REMATCH[1]}
word1
%% *
Aquí hay otra solución que usa la expansión de parámetros de shell . Se ocupa de múltiples espacios después de la primera palabra. El manejo de espacios delante de la primera palabra requiere una expansión adicional.
string='word1 word2'
echo ${string%% *}
word1
string='word1 word2 '
echo ${string%% *}
word1
Las %%
significa borrar la coincidencia más larga de *
(un espacio seguido de cualquier número de cualesquiera otros caracteres) en el arrastre parte de string
.
Me preguntaba cómo se midieron varias de las mejores respuestas en términos de velocidad. Probé lo siguiente:
1 @ mattbh
echo "..." | awk '{print $1;}'
2 @ ghostdog74's
string="..."; set -- $string; echo $1
3 @ boontawee-home's
echo "..." | { read -a array ; echo ${array[0]} ; }
y 4 @ boontawee-home's
echo "..." | { read first _ ; echo $first ; }
Los medí con el timeit de Python en un script Bash en un terminal Zsh en macOS, usando una cadena de prueba con 215 palabras de 5 letras. Hizo cada medición cinco veces (los resultados fueron todos para 100 bucles, el mejor de 3), y promediaron los resultados:
method time
--------------------------------
1. awk 9.2ms
2. set 11.6ms (1.26 * "1")
3. read -a 11.7ms (1.27 * "1")
4. read 13.6ms (1.48 * "1")
Buen trabajo, votantes 👏 ¡Los votos (a partir de este escrito) coinciden con la velocidad de las soluciones!
read -a
no es válido en el tablero).
echo "word1 word2" | cut -f 1 -d " "
cortar corta el primer campo (-f 1) de una lista de campos delimitados por la cadena "" (-d "")
read
es tu amigo:
Si la cadena está en una variable:
string="word1 word2"
read -r first _ <<< "$string"
printf '%s\n' "$first"
Si está trabajando en una tubería: primer caso: solo desea la primera palabra de la primera línea:
printf '%s\n' "word1 word2" "line2" | { read -r first _; printf '%s\n' "$first"; }
segundo caso: desea la primera palabra de cada línea:
printf '%s\n' "word1 word2" "worda wordb" | while read -r first _; do printf '%s\n' "$first"; done
Estos funcionan si hay espacios principales:
printf '%s\n' " word1 word2" | { read -r first _; printf '%s\n' "$first"; }
Estaba trabajando con un dispositivo incrustado que no tenía ni perl, awk ni python y lo hizo con sed en su lugar. Admite múltiples espacios antes de la primera palabra (que las soluciones cut
y bash
no manejaron).
VARIABLE=" first_word_with_spaces_before_and_after another_word "
echo $VARIABLE | sed 's/ *\([^ ]*\).*/\1/'
Esto fue muy útil al buscar ps
identificadores de proceso ya que las otras soluciones aquí que usan solo bash no pudieron eliminar los primeros espacios que se ps
usan para alinear.