@MestreLion Muchas veces las personas leen una pregunta para encontrar una solución a una variación de un problema. Este comienza con la premisa falsa que cutrespalda algo que no. Pero pensé que era útil, ya que obliga al lector a considerar el código que es más fácil de seguir. Yo quería una rápida, manera simple de utilización cutsin necesidad de utilizar múltiples sintaxis para awk, grep, sed, etc. La revcosa hizo el truco; muy elegante, y algo que nunca he considerado (incluso si es torpe para otras situaciones). También me gustó leer los otros enfoques de las otras respuestas.
Beejor
3
Vine aquí un problema de la vida real: quiero encontrar todas las diferentes extensiones de archivo en un árbol de origen, para actualizar un archivo .gitattributes con. Así find | cut -d. -f<last>es la inclinación natural
studog
Respuestas:
680
Podrías probar algo como esto:
echo 'maps.google.com'| rev | cut -d'.'-f 1| rev
Explicación
rev revierte "maps.google.com" para ser moc.elgoog.spam
cut usa punto (es decir, '.') como delimitador, y elige el primer campo, que es moc
por último, lo revertimos nuevamente para obtener com
No está usando solo cutpero está sin sedo awk. Entonces, ¿qué opina OP?
Jayesh Bhoi
77
@tom OP ha hecho más preguntas que solo esto en las últimas horas. Según nuestras interacciones con el OP sabemos que awk / sed / etc. no están permitidos en su tarea, pero no se ha hecho referencia a rev. Así que valió la pena
intentarlo
44
@zfus ya veo. Puede querer pegar otro revdespués.
Tom
17
doble revideal ideal!
Ford Guo
66
Impresionante, simple, perfecto, gracias por la explicación también: no hay suficientes personas que expliquen cada paso en largas cadenas de comandos canalizados
Pete
128
Utiliza un parámetro de expansión. Esto es mucho más eficiente que cualquier tipo de comando externo, cut(o grep) incluido.
data=foo,bar,baz,qux
last=${data##*,}
Ver BashFAQ # 100 para una introducción a la manipulación de cadenas nativas en bash.
@ErwinWessels: Porque bash es realmente lento. Use bash para ejecutar tuberías, no para procesar datos en masa. Quiero decir, esto es genial si ya tienes una línea de texto en una variable de shell, o si quieres while IFS= read -ra array_var; do :;done <(cmd)procesar algunas líneas. Pero para un archivo grande, ¡rev | cut | rev es probablemente más rápido! (Y, por supuesto awk será más rápido que eso.)
Peter Cordes
2
@PeterCordes, awk será más rápido para un archivo grande, seguro, pero se necesita un poco de información para superar los costos de inicio de factor constante. (También existen shells, como ksh93, con un rendimiento más cercano a awk, donde la sintaxis dada en esta respuesta sigue siendo válida; bash es excepcionalmente lento, pero ni siquiera está cerca de la única opción disponible).
Charles Duffy
1
Gracias @PeterCordes; como de costumbre, supongo que cada herramienta tiene sus casos de uso.
Erwin Wessels
1
Esta es, con mucho, la forma más rápida y concisa de recortar una sola variable dentro de un bashscript (suponiendo que ya esté usando un bashscript). No es necesario llamar a nada externo.
Ken Sharp
1
@Balmipour, ... sin embargo, reves específico de cualquier sistema operativo que esté utilizando que lo proporcione, no está estandarizado en todos los sistemas UNIX. Consulte la lista de capítulos de la sección POSIX sobre comandos y utilidades ; no está allí. Y de hecho no${var##prefix_pattern} es específico de bash; está en el estándar POSIX sh , consulte el final de la sección 2.6.2 (vinculado), por lo que , a diferencia , siempre está disponible en cualquier shell compatible. rev
Charles Duffy
89
No es posible usar solo cut. Aquí hay una manera de usar grep:
Para hacer lo contrario, y encontrar todo excepto el último campo:grep -o '^.*,'
Ariel
2
Esto fue especialmente útil, porque revagregué un problema de caracteres unicode multibyte en mi caso.
Brice
3
Intenté hacer esto en MinGW pero mi versión grep no admite -o, así que usé el sed 's/^.*,//'que reemplaza todos los caracteres hasta e incluyendo la última coma con una cadena vacía.
TamaMcGlinn
46
¿Sin awk? ... Pero es tan simple con awk:
echo 'maps.google.com'| awk -F.'{print $NF}'
AWK es una herramienta mucho más poderosa para tener en tu bolsillo. -F si para el separador de campo NF es el número de campos (también representa el índice del último)
Esto es universal y funciona exactamente como se esperaba cada vez. En este escenario, usar cutpara lograr la salida final del OP es como usar una cuchara para "cortar" el bistec (juego de palabras :)). awkEs el cuchillo de carne.
Hickory420
3
Evite el uso innecesario de echoeso puede ralentizar el script para archivos largos awk -F. '{print $NF}' <<< 'maps.google.com'.
Con esta solución, el número de campos puede ser desconocido y variar de vez en cuando. Sin embargo, como la longitud de la línea no debe exceder los caracteres o campos LINE_MAX, incluido el carácter de nueva línea, un número arbitrario de campos nunca puede ser parte como una condición real de esta solución.
Sí, una solución muy tonta, pero creo que la única que cumple los criterios.
Esto no utiliza sedo awksino que además no utiliza cuttampoco, así que no estoy muy seguro de si se califica como una respuesta a la pregunta de su redacción.
Esto no funciona bien si se procesan cadenas de entrada que pueden contener barras diagonales. Una solución para esa situación sería reemplazar la barra diagonal con algún otro carácter que sepa que no es parte de una cadena de entrada válida. Por ejemplo, el carácter pipe ( |) tampoco está permitido en los nombres de archivo, por lo que esto funcionaría:
Necesita comillas dobles alrededor de los argumentos echopara que esto funcione de manera confiable y sólida. Consulte stackoverflow.com/questions/10067266/…
tripleee el
0
Si tiene un archivo llamado filelist.txt que es una lista de rutas como la siguiente: c: /dir1/dir2/file1.h c: /dir1/dir2/dir3/file2.h
entonces puede hacer esto: rev filelist.txt | cortar -d "/" -f1 | Rdo
Agregar un enfoque a esta vieja pregunta solo por el gusto de hacerlo:
$ cat input.file # file containing input that needs to be processed
a;b;c;d;e
1;2;3;4;5
no delimiter here
124;adsf;15454
foo;bar;is;null;info
$ cat tmp.sh # showing off the script to do the job#!/bin/bash
delim=';'while read -r line;dowhile[["$line"=~"$delim"]];do
line=$(cut -d"$delim"-f 2-<<<"$line")done
echo "$line"done< input.file
$ ./tmp.sh # output of above script/processed input file
e
5
no delimiter here
15454
info
Además de bash, solo se usa corte. Bueno, y echo, supongo.
Meh, ¿por qué no solo eliminas el corte por completo y solo usas bash ... x] para while read -r line; do echo ${line/*;}; done <input.fileobtener el mismo resultado.
Kaffe Myers
-1
Me di cuenta de que si solo nos aseguramos de que exista un delimitador final, funciona. Entonces, en mi caso, tengo delimitadores de comas y espacios en blanco. Añado un espacio al final;
cut
comando :)? ¿Por qué no otros comandos de Linux?sed
oawk
:perl -pe 's/^.+\s+([^\s]+)$/$1/'
.cut
respalda algo que no. Pero pensé que era útil, ya que obliga al lector a considerar el código que es más fácil de seguir. Yo quería una rápida, manera simple de utilizacióncut
sin necesidad de utilizar múltiples sintaxis paraawk
,grep
,sed
, etc. Larev
cosa hizo el truco; muy elegante, y algo que nunca he considerado (incluso si es torpe para otras situaciones). También me gustó leer los otros enfoques de las otras respuestas.find | cut -d. -f<last>
es la inclinación naturalRespuestas:
Podrías probar algo como esto:
Explicación
rev
revierte "maps.google.com" para sermoc.elgoog.spam
cut
usa punto (es decir, '.') como delimitador, y elige el primer campo, que esmoc
com
fuente
cut
pero está sinsed
oawk
. Entonces, ¿qué opina OP?rev
después.rev
ideal ideal!Utiliza un parámetro de expansión. Esto es mucho más eficiente que cualquier tipo de comando externo,
cut
(ogrep
) incluido.Ver BashFAQ # 100 para una introducción a la manipulación de cadenas nativas en bash.
fuente
while IFS= read -ra array_var; do :;done <(cmd)
procesar algunas líneas. Pero para un archivo grande, ¡rev | cut | rev es probablemente más rápido! (Y, por supuesto awk será más rápido que eso.)bash
script (suponiendo que ya esté usando unbash
script). No es necesario llamar a nada externo.rev
es específico de cualquier sistema operativo que esté utilizando que lo proporcione, no está estandarizado en todos los sistemas UNIX. Consulte la lista de capítulos de la sección POSIX sobre comandos y utilidades ; no está allí. Y de hecho no${var##prefix_pattern}
es específico de bash; está en el estándar POSIX sh , consulte el final de la sección 2.6.2 (vinculado), por lo que , a diferencia , siempre está disponible en cualquier shell compatible.rev
No es posible usar solo
cut
. Aquí hay una manera de usargrep
:Reemplace la coma por otros delimitadores.
fuente
grep -o '^.*,'
rev
agregué un problema de caracteres unicode multibyte en mi caso.sed 's/^.*,//'
que reemplaza todos los caracteres hasta e incluyendo la última coma con una cadena vacía.¿Sin awk? ... Pero es tan simple con awk:
AWK es una herramienta mucho más poderosa para tener en tu bolsillo. -F si para el separador de campo NF es el número de campos (también representa el índice del último)
fuente
cut
para lograr la salida final del OP es como usar una cuchara para "cortar" el bistec (juego de palabras :)).awk
Es el cuchillo de carne.echo
eso puede ralentizar el script para archivos largosawk -F. '{print $NF}' <<< 'maps.google.com'
.Hay múltiples formas Puedes usar esto también.
Obviamente, la entrada de espacio en blanco para el comando tr debe reemplazarse con el delimitador que necesita.
fuente
Esta es la única solución posible para usar nada más que cortar:
Con esta solución, el número de campos puede ser desconocido y variar de vez en cuando. Sin embargo, como la longitud de la línea no debe exceder los caracteres o campos LINE_MAX, incluido el carácter de nueva línea, un número arbitrario de campos nunca puede ser parte como una condición real de esta solución.
Sí, una solución muy tonta, pero creo que la única que cumple los criterios.
fuente
cut -f2-
en un bucle hasta que la salida ya no cambie.Si su cadena de entrada no contiene barras diagonales, entonces puede usar
basename
y una subshell:Esto no utiliza
sed
oawk
sino que además no utilizacut
tampoco, así que no estoy muy seguro de si se califica como una respuesta a la pregunta de su redacción.Esto no funciona bien si se procesan cadenas de entrada que pueden contener barras diagonales. Una solución para esa situación sería reemplazar la barra diagonal con algún otro carácter que sepa que no es parte de una cadena de entrada válida. Por ejemplo, el carácter pipe (
|
) tampoco está permitido en los nombres de archivo, por lo que esto funcionaría:fuente
lo siguiente implementa la sugerencia de un amigo
fuente
echo
para que esto funcione de manera confiable y sólida. Consulte stackoverflow.com/questions/10067266/…Si tiene un archivo llamado filelist.txt que es una lista de rutas como la siguiente: c: /dir1/dir2/file1.h c: /dir1/dir2/dir3/file2.h
entonces puede hacer esto: rev filelist.txt | cortar -d "/" -f1 | Rdo
fuente
Agregar un enfoque a esta vieja pregunta solo por el gusto de hacerlo:
Además de bash, solo se usa corte. Bueno, y echo, supongo.
fuente
while read -r line; do echo ${line/*;}; done <input.file
obtener el mismo resultado.Me di cuenta de que si solo nos aseguramos de que exista un delimitador final, funciona. Entonces, en mi caso, tengo delimitadores de comas y espacios en blanco. Añado un espacio al final;
fuente
ans="a, b, c"
produceb
, que no cumple con los requisitos de "número de campos son desconocidos o cambian con cada línea" .