4 votos

División de cadena, extraer caracteres y poniendo de nuevo juntos

Tengo cadenas en forma de wva/sia/e1 , bct/e2 , sv/de/e11 . Siempre es <Part1>/e<NUM> o <Part1>/<Part2>/e<NUM> . Lo que quiero es acortar las cuerdas manteniendo las primeras letras de las partes y de abandono de las barras y e:

wva/sia/e1 > ws1
bct/e2 > b2
sv/de/e11 > sd11

¿Cómo puedo hacer que el interior un script sh?

Edit: La cadena representa un nombre de trabajo:

[...]
job_name=$1 # e.g. 'wva/sia/e1'
job_name=cut_name(job_name) # e.g. 'ws1'
[...]

5voto

Jacob Vlijm Puntos 24137

En la forma de una secuencia de comandos como lo que pides:

#!/usr/bin/env python3
import sys

# read the input, split by /
st = sys.argv[1].split("/")
# get the first char of all sections *but* the last one
# add the last *from* the first character
print("".join([s[0] for s in st][:-1])+st[-1][1:])

Tenga en cuenta que esto funciona para cualquier longitud, por ejemplo:

wva/sia/bct/wva/sia/e1

se convertirá en

wsbws1

mientras que la última sección termina con /e<num>

El uso de

  1. Copie la secuencia de comandos en un archivo vacío, guárdelo como rearrange.py
  2. Ejecutar con la cadena como argumento, por ejemplo:

    python3 /path/to/rearrange.py wva/sia/e1
    
    > ws1
    

Explicación

La secuencia de comandos bastante explica a sí mismo, pero también se comentó.

3voto

Serg Puntos 17677

Bash 4.3 One-liner

Vamos a decir que no necesitamos de una completa secuencia de comandos. Bash tiene suficientes capacidades que nos permiten conseguir lejos con un one-liner. He aquí uno:

bash-4.3$ (read -r var ;IFS='/'; printf "%c" ${var%/*};echo ${var##*[^0-9]}) <<<  "sv/de/e11"
sd11

¿Qué está pasando ?

  • todo lo que sucede en subshell, por tanto, ( ) de todo el comando
  • utilizamos aquí la cadena <<< a enviar la entrada , y la subshell comando obtiene a través de read -r var y almacena en var variable
  • nos pusimos IFS='/' , de modo que el subshell rompe var en artículos separados en / separador. Esto es importante para que la palabra de dividir.
  • a continuación, utilizamos el sufijo de eliminación de ${var%/*} a deshacerse de la última parte antes de / . En el ejemplo de arriba sería e11
  • printf "%c" verá el resultado de ${var%/*} como sv de debido a la palabra de división y el sufijo de la eliminación mencionados anteriormente (magia, sí). Porque de lo printf palabras %c va a imprimir sólo la primera letra, pero lo hará para cada argumento de línea de comandos que recibe, por lo que para sv de que es la salida s y d. La impresión se realiza sin salto de línea, por lo tanto, parece como si los caracteres se escriben en la secuencia
  • echo ${var##*[^0-9]} hace uso de prefijo de eliminación para deshacerse de todos los no-dígito de caracteres en la cadena de entrada, obteniendo sólo el último dígito

Hay otro one-liner enfoque, que es un poco más explícito y natural a C-como programadores.

bash-4.3$ (read -r inp;IFS='/';arr=( $inp ); for ((i=0;i<$(( ${#arr[@]} -1 ));i++));do printf "%s" ${arr[$i]:0:1};done;printf "%s\n" ${inp##*[^0-9]}) <<<  "sv/de/e11"
sd11

¿Qué es esta magia ? He aquí una explicación:

  • Todo lo que sucede en subshell, por tanto, () de todo el comando.
  • Utilizamos aquí-cadena <<< para enviar el elemento que queramos en el comando de entrada de secuencia, y el comando obtiene a través de read -r inp comando y lo almacena en inp variable
  • Siguiente cambiamos IFS variable, por lo que podemos descomponer todo en una matriz.
  • podemos iterar sobre todos los elementos hasta el penúltimo, el uso de C-estilo bucle for for ((initial condition; test condition; post condition)) ; do ... done
  • el $(( ${#arr[@]} - 1 )) es la expansión aritmética donde le restamos 1 a la longitud de la matriz ${#arr[@]}
  • el printf "%s" ${arr[$i]:0:1} nos permite usar el parámetro de expansión donde podemos imprimir sólo la primera letra de cada elemento, y printf "%s" imprime sin salto de línea, por lo que aparece como estamos de impresión de cada letra en la misma línea.
  • finalmente, una vez que el bucle es más, tomamos original de entrada de texto y deshacerse de todo lo que no es dígitos utilizando el prefijo de la extracción ${#*[^0-9]}

Secuencia de comandos de enfoque

Dado que la pregunta pide una secuencia de comandos de shell, aquí está uno en bash 4.3 , que es casi el mismo método que el anterior, pero más explícito:

#!/bin/bash
IFS='/'
items=( $1 )
counter=1
for i in ${items[@]}
do
    if [ $counter -eq ${#items[@]}  ];
    then
        # note the space before -1
        printf "%s\n" "${i##*[^0-9]}"
    else
        printf "%s" "${i:0:1}"
    fi
    counter=$(($counter + 1)) 
done

La forma en que esto funciona es así:

  • dada una cadena en la línea de comandos como argumento, nos interno separador de campo a / , y permiten a bash para realizar palabra dividir para romper la cadena en una matriz llamada items
  • podemos iterar sobre todos los elementos de la matriz ${items[@]} , mientras se mantiene un registro de elemento que estamos en el uso de la variable de contador y saber el número de elementos en la matriz ( ${#items[@]} parte).
  • El if-statement es lo que nos permite elegir el carácter específico de cada elemento. Mediante el parámetro de expansión, primer personaje a través de${i:0:1}. El uso de prefijo más largo de eliminación de ${variable##prefix}, eliminamos todos los no-dígito de los personajes de la última cadena en printf "%s\n" "${i##*[^0-9]}".

Aquí está en acción:

$ ./shorten_string.sh "wva/sia/e1"                         
ws1
$ ./shorten_string.sh "bct/e2"                             
b2
$ ./shorten_string.sh  "sv/de/e11"                     
sd11

1voto

Zanna Puntos 502

OK, no una secuencia de comandos, pero se puede poner en una secuencia de comandos (también esto es muy poco elegante, ya que no pudo lidiar con ambas formas en un solo comando)

$ sed -r 's:(.).*/(.).*/e([0-9]+):\1\2\3:;s:(.).*/e([0-9]+):\1\2:' file
ws1
b2
sd11

Notas

  • -r uso ERE
  • s:old:new: reemplace old con new
  • .* cualquier número de caracteres
  • (.) salvar a uno de los personajes de esta posición
  • ([0-9]+) ahorrar al menos un dígito aquí
  • ; separa comandos, como en el shell
  • \1 referencias inversas a los personajes guardan con ()

EnMiMaquinaFunciona.com

EnMiMaquinaFunciona es una comunidad de administradores de sistemas en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros sysadmin, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X