AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 412952
Accepted
Pro Backup
Pro Backup
Asked: 2017-12-26 04:45:05 +0800 CST2017-12-26 04:45:05 +0800 CST 2017-12-26 04:45:05 +0800 CST

Existe uma alternativa de substituição/expansão de parâmetro para "| cut -f1,2,3 -d:" também conhecido como trim após e incluindo a n-ésima ocorrência de caractere?

  • 772

Uma versão antigaipconfig de (dentro do initramfs) requer que a entrada do usuário forneça apenas até 7 elementos separados por dois pontos, como:

ip=client-ip:server-ip:gw-ip:netmask:hostname:device:autoconf

resultar em um ipconfigerro quando os usuários fornecem mais de 7 elementos.

Portanto, o extra (2 resolvedores de DNS) deve ser cortado.

Isso pode ser feito dentro de um subshellwith cut, como:

validated_input=$(echo ${user_input} | cut -f1,2,3,4,5,6,7 -d:)

Como isso pode cutser escrito usando (b)ashexpansão/substituição de parâmetros?

Sem:

  • lançamento de subshell(s)/subprocesso(s) (piping)
  • IFS-wrangling/mangling

Devido à (1) velocidade, consulte Usando a substituição de variável bash em vez de cut/awk e (2) aprendizado.


Em outras palavras: Como fazer uma pesquisa para a n-ésima (7ª) ocorrência de caractere e remover/aparar tudo daí até o final da string?

string cut
  • 3 3 respostas
  • 1076 Views

3 respostas

  • Voted
  1. ilkkachu
    2017-12-26T05:21:38+08:002017-12-26T05:21:38+08:00

    Com uma regex:

    $ var=a:b:c:d:e:f:g:h:i:j:k:l
    $ [[ $var =~ ([^:]*:){6}([^:]*) ]] && echo "${BASH_REMATCH[0]}"
    a:b:c:d:e:f:g
    

    Isso deve funcionar no shell padrão:

    #!/bin/sh
    var=a:b:c:d:e:f:g:h:i:j:k:l
    while true; do 
        case "$var" in
            *:*:*:*:*:*:*:*) var=${var%:*} ;;
            *) break ;;
        esac
    done
    echo "$var"
    

    Ou se permitirmos a configuração IFSpela duração de read:

    $ IFS=: read -a arr <<< "$var"
    $ arr=("${arr[@]:0:7}")
    $ echo "${arr[@]}"
    a b c d e f g
    $ printf "%s:%s:%s:%s:%s:%s:%s\n" "${arr[0]}" "${arr[1]}" "${arr[2]}" "${arr[3]}" "${arr[4]}" "${arr[5]}"  "${arr[6]}" 
    a:b:c:d:e:f:g
    
    • 5
  2. Best Answer
    jesse_b
    2017-12-26T06:02:08+08:002017-12-26T06:02:08+08:00

    Isso usa apenas expansão de parâmetro:

    ${var%:"${var#*:*:*:*:*:*:*:}"}
    

    Exemplo :

    $ var=client-ip:server-ip:gw-ip:netmask:hostname:device:autoconf:morefields:another:youwantanother:haveanother:
    $ echo "${var%:"${var#*:*:*:*:*:*:*:}"}"
    client-ip:server-ip:gw-ip:netmask:hostname:device:autoconf
    

    Obrigado ilkkachu por vir com uma correção para o trailing :!


    ${parameter#word}
    ${parameter##word}
    

    A palavra é expandida para produzir um padrão exatamente como na expansão de nome de arquivo (consulte Expansão de nome de arquivo). Se o padrão corresponder ao início do valor expandido do parâmetro, o resultado da expansão será o valor expandido do parâmetro com o padrão correspondente mais curto (o caso '#') ou o padrão correspondente mais longo (o caso '##') excluído. Se o parâmetro for '@' ou ' ', a operação de remoção de padrão é aplicada a cada parâmetro posicional por vez, e a expansão é a lista resultante. Se o parâmetro for uma variável de matriz subscrita com '@' ou ' ', a operação de remoção de padrão será aplicada a cada membro da matriz por vez e a expansão será a lista resultante.

    Isso tentará corresponder ao início do seu parâmetro e, se corresponder, o removerá.

    Exemplo :

    $ var=a:b:c:d:e:f:g:h:i
    $ echo "${var#a}"
    :b:c:d:e:f:g:h:i
    $ echo "${var#a:b:}"
    c:d:e:f:g:h:i
    $ echo "${var#*:*:}"
    c:d:e:f:g:h:i
    $ echo "${var##*:}"    # Two hashes make it greedy
    i
    

    ${parameter%word}
    ${parameter%%word}
    

    A palavra é expandida para produzir um padrão assim como na expansão de nome de arquivo. Se o padrão corresponder a uma parte final do valor expandido do parâmetro, o resultado da expansão será o valor do parâmetro com o padrão de correspondência mais curto (o caso '%') ou o padrão de correspondência mais longo (o caso '%%') excluído. Se o parâmetro for '@' ou ' ', a operação de remoção de padrão é aplicada a cada parâmetro posicional por vez, e a expansão é a lista resultante. Se o parâmetro for uma variável de matriz subscrita com '@' ou ' ', a operação de remoção de padrão será aplicada a cada membro da matriz por vez e a expansão será a lista resultante.

    Isso tentará corresponder ao final do seu parâmetro e, se corresponder, o removerá.

    Exemplo :

    $ var=a:b:c:d:e:f:g:h:i
    $ echo "${var%i}"
    a:b:c:d:e:f:g:h:
    $ echo "${var%:h:i}"
    a:b:c:d:e:f:g
    $ echo "${var%:*:*}"
    a:b:c:d:e:f:g
    $ echo "${var%%:*}"    # Two %s make it greedy
    a
    

    Então na resposta:

    ${var%:"${var#*:*:*:*:*:*:*:}"}
    

    (observe as aspas ao redor ${var#...}para que seja tratado como uma string literal (não um padrão) a ser removido do final de $var).

    Quando aplicado a:

    var=client-ip:server-ip:gw-ip:netmask:hostname:device:autoconf:morefields:another:youwantanother:haveanother:
    

    ${var#*:*:*:*:*:*:*:}=morefields:another:youwantanother:haveanother:

    Isso é expandido para dentro ${var%: ... }assim:

    ${var%:morefields:another:youwantanother:haveanother:}

    Então você está dizendo me dê:

    client-ip:server-ip:gw-ip:netmask:hostname:device:autoconf:morefields:another:youwantanother:haveanother:
    

    Mas corte :morefields:another:youwantanother:haveanother:a ponta.

    O Manual de Referência do Bash ( 3.5.3 )

    • 5
  3. Stéphane Chazelas
    2018-01-15T10:57:42+08:002018-01-15T10:57:42+08:00

    Em zsh:

    $ ip=client-ip:server-ip:gw-ip:netmask:hostname:device:autoconf:x:y:z
    $ echo ${(j(:))${"${(@s(:))ip}"[1,7]}}
    client-ip:server-ip:gw-ip:netmask:hostname:device:autoconf
    
    • ${(s(:))var}dividido em:
    • "${(@)...}": certifique-se de preservar os elementos vazios (como em "$@")
    • ${var[1,7]}elementos 1 a 7
    • ${(j(:))var}juntar elementos em:

    Ou você pode fazer:

    $ set -o extendedglob
    $ echo ${(M)ip##([^:]#:)(#c0,6)[^:]#}
    client-ip:server-ip:gw-ip:netmask:hostname:device:autoconf
    
    • ${var##pattern}como em ksh, retire a parte inicial mais longa correspondente ao padrão.
    • (M): expandido para a parte combinada em vez de removê-la
    • x#: 0 ou mais xs (como regexp *)
    • (#c0,6)de 0 a 6 do átomo anterior (como ksh's {x,y}(...))
    • 0

relate perguntas

  • Uso de sed com aspas duplas

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Matriz JSON para bash variáveis ​​usando jq

    • 4 respostas
  • Marko Smith

    A data pode formatar a hora atual para o fuso horário GMT? [duplicado]

    • 2 respostas
  • Marko Smith

    bash + lê variáveis ​​e valores do arquivo pelo script bash

    • 4 respostas
  • Marko Smith

    Como posso copiar um diretório e renomeá-lo no mesmo comando?

    • 4 respostas
  • Marko Smith

    conexão ssh. Conexão X11 rejeitada devido a autenticação incorreta

    • 3 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Marko Smith

    comando systemctl não funciona no RHEL 6

    • 3 respostas
  • Marko Smith

    rsync porta 22 e 873 uso

    • 2 respostas
  • Marko Smith

    snap /dev/loop em 100% de utilização -- sem espaço livre

    • 1 respostas
  • Marko Smith

    chave de impressão jq e valor para todos no subobjeto

    • 2 respostas
  • Martin Hope
    EHerman Matriz JSON para bash variáveis ​​usando jq 2017-12-31 14:50:58 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Drux A data pode formatar a hora atual para o fuso horário GMT? [duplicado] 2017-12-26 11:35:07 +0800 CST
  • Martin Hope
    AllisonC Como posso copiar um diretório e renomeá-lo no mesmo comando? 2017-12-22 05:28:06 +0800 CST
  • Martin Hope
    Steve Como as permissões de arquivo funcionam para o usuário "root"? 2017-12-22 02:46:01 +0800 CST
  • Martin Hope
    Bagas Sanjaya Por que o Linux usa LF como caractere de nova linha? 2017-12-20 05:48:21 +0800 CST
  • Martin Hope
    Cbhihe Altere o editor padrão para vim para _ sudo systemctl edit [unit-file] _ 2017-12-03 10:11:38 +0800 CST
  • Martin Hope
    showkey Como baixar o pacote não instalá-lo com o comando apt-get? 2017-12-03 02:15:02 +0800 CST
  • Martin Hope
    youxiao Por que os diretórios /home, /usr, /var, etc. têm o mesmo número de inode (2)? 2017-12-02 05:33:41 +0800 CST
  • Martin Hope
    user223600 gpg — o comando list-keys gera uid [ desconhecido ] depois de importar a chave privada para uma instalação limpa 2017-11-26 18:26:02 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve