Divida a string por delimitador e obtenha o N-ésimo elemento

Divida a string por delimitador e obtenha o N-ésimo elemento

Eu tenho uma string:

one_two_three_four_five

Preciso salvar em um Avalor variável twoe em Bvalor variável fourda string acima

Estou usando ksh.

Responder1

Use cutwith _como delimitador de campo e obtenha os campos desejados:

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

Você também pode usar echoand pipe em vez da string Here:

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

Exemplo:

$ s='one_two_three_four_five'

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

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

Esteja ciente de que, se $scontiver caracteres de nova linha, isso retornará uma string multilinha que contém o 2º /campo em cada linha de $s, não o 2º /campo em $s.

Responder2

Queria ver uma awkresposta, então aqui está uma:

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

Experimente on-line!

Responder3

Usando apenas construções POSIX sh, você pode usarconstruções de substituição de parâmetrospara analisar um delimitador por vez. Observe que este código pressupõe que existe o número necessário de campos, caso contrário, o último campo é repetido.

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, você pode usar uma substituição de parâmetro sem aspas comexpansão curingadesativado eIFSdefinido como o caractere delimitador(isso só funciona se o delimitador for um único caractere que não seja espaço em branco ou se qualquer sequência de espaço em branco for um delimitador).

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

Isso prejudica os parâmetros posicionais. Se você fizer isso em uma função, somente os parâmetros posicionais da função serão afetados.

Ainda outra abordagem para strings que não contêm caracteres de nova linha é usar o readmétodo interno.

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

Responder4

Com zshvocê poderia dividir a string (on _) em um array:

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

e então acesse cada/qualquer elemento por meio do índice do array:

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

Tenha em mente que in zsh(como a maioria dos outros shells, mas diferente de ksh/ bash)índices de array começam em 1.

Ou diretamente em uma expansão:

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

Ou usando uma função anônima para que os elementos fiquem disponíveis em seu $1, $2...:

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

informação relacionada