Por ejemplo, dado:
USCAGoleta9311734.5021-120.1287855805
Quiero extraer solo:
US
Por ejemplo, dado:
USCAGoleta9311734.5021-120.1287855805
Quiero extraer solo:
US
Respuestas:
Probablemente el método más eficiente, si está utilizando el bash
shell (y parece que lo es, según sus comentarios), es usar la variante de subcadena de expansión de parámetros:
pax> long="USCAGol.blah.blah.blah"
pax> short="${long:0:2}" ; echo "${short}"
US
Esto se establecerá short
para ser los dos primeros caracteres de long
. Si long
es más corto que dos caracteres, short
será idéntico a él.
Este método de shell generalmente es mejor si lo vas a hacer mucho (como 50,000 veces por informe como mencionas) ya que no hay sobrecarga de creación de procesos. Todas las soluciones que utilizan programas externos sufrirán esa sobrecarga.
Si también quisieras asegurar una longitud mínima , puedes rellenarlo de antemano con algo como:
pax> long="A"
pax> tmpstr="${long}.."
pax> short="${tmpstr:0:2}" ; echo "${short}"
A.
Esto garantizaría que algo menos de dos caracteres de longitud se rellenara a la derecha con puntos (o algo más, simplemente cambiando el carácter utilizado al crear tmpstr
). No está claro que necesites esto, pero pensé que lo pondría completo.
Dicho esto, hay varias maneras de hacer esto con programas externos (por ejemplo, si no tiene a su bash
disposición), algunas de las cuales son:
short=$(echo "${long}" | cut -c1-2)
short=$(echo "${long}" | head -c2)
short=$(echo "${long}" | awk '{print substr ($0, 0, 2)}'
short=$(echo "${long}" | sed 's/^\(..\).*/\1/')
Los primeros dos ( cut
y head
) son idénticos para una cadena de una sola línea; básicamente, ambos solo le devuelven los dos primeros caracteres. Se diferencian en que cut
le dará los dos primeros caracteres de cada línea yhead
le dará los dos primeros caracteres de toda la entrada.
El tercero usa la awk
función de subcadena para extraer los dos primeros caracteres y el cuarto usa los sed
grupos de captura (usando ()
y \1
) para capturar los dos primeros caracteres y reemplazar toda la línea con ellos. Ambos son similares a cut
: entregan los dos primeros caracteres de cada línea en la entrada.
Nada de eso importa si está seguro de que su entrada es una sola línea, todas tienen un efecto idéntico.
printf '%s'
en lugar de echo
en el caso de que haya caracteres extraños en la cadena: stackoverflow.com/a/40423558/895245 Para el POSIX obsesionado: head -c
no es POSIX, cut -c
y awk substr
son, sed \1
no estoy seguro.
la forma más fácil es
${string:position:length}
Donde esto extrae la $length
subcadena de $string
at$position
.
Este es un bash incorporado así que no se requiere awk o sed.
Usted ha conseguido varias respuestas buenas y me gustaría ir con el Bash incorporado a mí mismo, pero ya que preguntas acerca sed
y awk
y ( casi soluciones) que nadie más ofrece en base a ellas, les ofrecen éstas:
echo "USCAGoleta9311734.5021-120.1287855805" | awk '{print substr($0,0,2)}'
y
echo "USCAGoleta9311734.5021-120.1287855805" | sed 's/\(^..\).*/\1/'
El awk
uno debería ser bastante obvio, pero aquí hay una explicación sed
:
substr($0,1,2)
.
Si estás dentro bash
, puedes decir:
bash-3.2$ var=abcd
bash-3.2$ echo ${var:0:2}
ab
Esto puede ser justo lo que necesitas ...
Solo grep:
echo 'abcdef' | grep -Po "^.." # ab
-P
opción para acortarla. Todas las expresiones regulares entenderán ese patrón.
Puedes usar printf
:
$ original='USCAGoleta9311734.5021-120.1287855805'
$ printf '%-.2s' "$original"
US
Muy tarde, pero aquí está
sed 's/.//3g'
O
awk NF=1 FPAT=..
O
perl -pe '$_=unpack a2'
Si desea utilizar secuencias de comandos de shell y no confiar en extensiones que no son posix (como los llamados bashisms), puede utilizar técnicas que no requieren herramientas externas de forking como grep, sed, cut, awk, etc., que luego Haz que tu guión sea menos eficiente. Quizás la eficiencia y la portabilidad posix no sean importantes en su caso de uso. Pero en caso de que lo sea (o simplemente como un buen hábito), puede usar el siguiente método de opción de expansión de parámetros para extraer los dos primeros caracteres de una variable de shell:
$ sh -c 'var=abcde; echo "${var%${var#??}}"'
ab
Utiliza la expansión del parámetro "prefijo más pequeño" para eliminar los dos primeros caracteres (esta es la ${var#??}
parte), luego la expansión del parámetro "sufijo más pequeño" (el${var%
parte) para eliminar la cadena de todo menos los dos primeros caracteres del original valor.
Este método se describió previamente en esta respuesta a la pregunta "Shell = Verificar si la variable comienza con #". Esa respuesta también describe un par de métodos de expansión de parámetros similares que se pueden usar en un contexto ligeramente diferente al que se aplica a la pregunta original aquí.
Si su sistema está usando un shell diferente (no bash
), pero su sistema sí bash
, aún puede usar la manipulación de cadena inherente bash
invocando bash
con una variable:
strEcho='echo ${str:0:2}' # '${str:2}' if you want to skip the first two characters and keep the rest
bash -c "str=\"$strFull\";$strEcho;"
bash
si aún no lo está utilizando.
Solo por diversión, agregaré algunos que, aunque son demasiado complicados e inútiles, no se mencionaron:
head -c 2 <( echo 'USCAGoleta9311734.5021-120.1287855805')
echo 'USCAGoleta9311734.5021-120.1287855805' | dd bs=2 count=1 status=none
sed -e 's/^\(.\{2\}\).*/\1/;' <( echo 'USCAGoleta9311734.5021-120.1287855805')
cut -c 1-2 <( echo 'USCAGoleta9311734.5021-120.1287855805')
python -c "print(r'USCAGoleta9311734.5021-120.1287855805'[0:2])"
ruby -e 'puts "USCAGoleta9311734.5021-120.1287855805"[0..1]'
si mystring = USCAGoleta9311734.5021-120.1287855805
print substr(mystring,0,2)
nos imprimiría
donde 0 es la posición de inicio y 2 es cómo muchos caracteres para leer
awk
. Lo siento, no pude saber al principio.
¿Es esto lo que buscas?
my $string = 'USCAGoleta9311734.5021-120.1287855805';
my $first_two_chars = substr $string, 0, 2;
ref: substr
perl -e 'print substr $ARGV[0], 0, 2' 'USCAGoleta9311734.5021-120.1287855805'