Divida la cadena por delimitador y obtenga el enésimo elemento

Divida la cadena por delimitador y obtenga el enésimo elemento

Tengo una cadena:

one_two_three_four_five

Necesito guardar en un Avalor variable twoy en Bun valor variable fourde la cadena anterior

Estoy usando ksh.

Respuesta1

Úselo cutcon _como delimitador de campo y obtenga los campos deseados:

A="$(cut -d'_' -f2 <<<'one_two_three_four_five')"
B="$(cut -d'_' -f4 <<<'one_two_three_four_five')"

También puedes usar echoy canalizar en lugar de la cadena Here:

A="$(echo 'one_two_three_four_five' | cut -d'_' -f2)"
B="$(echo 'one_two_three_four_five' | cut -d'_' -f4)"

Ejemplo:

$ s='one_two_three_four_five'

$ A="$(cut -d'_' -f2 <<<"$s")"
$ echo "$A"
two

$ B="$(cut -d'_' -f4 <<<"$s")"
$ echo "$B"
four

Tenga en cuenta que si $scontiene caracteres de nueva línea, devolverá una cadena de varias líneas que contiene el segundo / cuarto campo en cada línea de $s, no el segundo / cuarto campo en $s.

Respuesta2

Quería ver una awkrespuesta, así que aquí hay una:

A=$(awk -F_ '{print $2}' <<< 'one_two_three_four_five')
B=$(awk -F_ '{print $4}' <<< 'one_two_three_four_five')  

¡Pruébalo en línea!

Respuesta3

Usando solo construcciones POSIX sh, puede usarconstrucciones de sustitución de parámetrospara analizar un delimitador a la vez. Tenga en cuenta que este código supone que existe el número requerido de campos; de lo contrario, se repite el último campo.

string='one_two_three_four_five'
remainder="$string"
first="${remainder%%_*}"; remainder="${remainder#*_}"
second="${remainder%%_*}"; remainder="${remainder#*_}"
third="${remainder%%_*}"; remainder="${remainder#*_}"
fourth="${remainder%%_*}"; remainder="${remainder#*_}"

Alternativamente, puede utilizar una sustitución de parámetros sin comillas conexpansión comodíndiscapacitado yIFSestablecido en el carácter delimitador(Esto solo funciona si el delimitador es un único carácter que no es un espacio en blanco o si cualquier secuencia de espacios en blanco es un delimitador).

string='one_two_three_four_five'
set -f; IFS='_'
set -- $string
second=$2; fourth=$4
set +f; unset IFS

Esto afecta los parámetros posicionales. Si hace esto en una función, solo se verán afectados los parámetros posicionales de la función.

Otro enfoque más para cadenas que no contienen caracteres de nueva línea es utilizar la readfunción incorporada.

IFS=_ read -r first second third fourth trail <<'EOF'
one_two_three_four_five
EOF

Respuesta4

Con zshusted podría dividir la cadena (on _) en una matriz:

non_empty_elements=(${(s:_:)string})
all_elements=("${(@s:_:)string}")

y luego acceder a cada/cualquier elemento a través del índice de matriz:

print -r -- ${all_elements[4]}

Tenga en cuenta que en zsh(como la mayoría de los otros shells, pero a diferencia de ksh/ bash)Los índices de matriz comienzan en 1..

O directamente en una expansión:

print -r -- "${${(@s:_:)string}[4]}"

O usando una función anónima para que los elementos estén disponibles en su $1, $2…:

(){print -r -- $4} "${(@s:_:)string}"

información relacionada