A maneira mais simples de extrair a substring no shell Unix?

5

Qual é a maneira mais simples de extrair a substring no shell Unix (com regex)?

Simples significa:

  • menos recurso
  • menos opções
  • menos estudo

Atualizar

Percebi que a regex em si está em conflito com a simplicidade e escolhi a mais simples cut como a resposta escolhida. Sinto muito por uma pergunta vaga. Eu mudei o título para representar o estado atual deste controle de qualidade com mais precisão.

    
por Eonil 04.09.2010 / 18:08

4 respostas

9

cut pode ser útil:

$ echo hello | cut -c1,3
hl
$ echo hello | cut -c1-3
hel
$ echo hello | cut -c1-4
hell
$ echo hello | cut -c4-5
lo

O Shell Builtins também é bom para isso, aqui está um exemplo de script:

#!/bin/bash
# Demonstrates shells built in ability to split stuff.  Saves on
# using sed and awk in shell scripts. Can help performance.

shopt -o nounset
declare -rx       FILENAME=payroll_2007-06-12.txt

# Splits
declare -rx   NAME_PORTION=${FILENAME%.*}     # Left of .
declare -rx      EXTENSION=${FILENAME#*.}     # Right of .
declare -rx           NAME=${NAME_PORTION%_*} # Left of _
declare -rx           DATE=${NAME_PORTION#*_} # Right of _
declare -rx     YEAR_MONTH=${DATE%-*}         # Left of _
declare -rx           YEAR=${YEAR_MONTH%-*}   # Left of _
declare -rx          MONTH=${YEAR_MONTH#*-}   # Left of _
declare -rx            DAY=${DATE##*-}        # Left of _

clear

echo "  Variable: (${FILENAME})"
echo "  Filename: (${NAME_PORTION})"
echo " Extension: (${EXTENSION})"
echo "      Name: (${NAME})"
echo "      Date: (${DATE})"
echo "Year/Month: (${YEAR_MONTH})"
echo "      Year: (${YEAR})"
echo "     Month: (${MONTH})"
echo "       Day: (${DAY})"

Essa saída:

  Variable: (payroll_2007-06-12.txt)
  Filename: (payroll_2007-06-12)
 Extension: (txt)
      Name: (payroll)
      Date: (2007-06-12)
Year/Month: (2007-06)
      Year: (2007)
     Month: (06)
       Day: (12)

E, de acordo com o Gnudif acima, há sempre sed / awk / perl para quando as coisas ficam realmente difíceis.

    
por 04.09.2010 / 18:32
2

Unix shells não possuem tradicionalmente suporte a regex embutido. Bash e Zsh fazem isso, então se você usar o operador =~ para comparar uma string com uma regex, então:

Você pode obter substrings a partir da matriz $BASH_REMATCH no bash.

Em Zsh, se a opção BASH_REMATCH shell estiver definida, o valor estará no array $BASH_REMATCH , senão estará no par de variáveis $MATCH/$match (um escalar, o outro um array). Se a opção RE_MATCH_PCRE estiver configurada, o mecanismo PCRE será usado, caso contrário, as bibliotecas regexp do sistema, para uma correspondência de sintaxe regexp estendida, conforme bash.

Então, mais simples: se você estiver usando o bash:

if [[ "$variable" =~ unquoted.*regex ]]; then
  matched_portion="${BASH_REMATCH[0]}"
  first_substring="${BASH_REMATCH[1]}"
fi

Se você não estiver usando o Bash ou o Zsh, fica mais complicado, já que você precisa usar comandos externos.

    
por 05.01.2011 / 11:08
2

grep e sed são provavelmente as ferramentas que você deseja, dependendo da estrutura do texto.

sed deve fazer o truque, se você não sabe o que é a substring, mas conhece algum padrão que está ao redor dele.

por exemplo, se você quiser encontrar uma subseqüência de dígitos que comece com um sinal "#", escreva algo como:

sed 's/^.*#\([0-9]\+\)//g' yourfile

O grep poderia fazer algo semelhante, mas a questão é o que você precisa fazer com a substring e se estamos falando de um texto delimitado de fim de linha normal ou não.

    
por 04.09.2010 / 18:25
1

Considere também /usr/bin/expr .

$ expr substr hello 2 3
ell

Você também pode combinar padrões com o início das strings.

$ expr match hello h
1

$ expr match hello hell
4

$ expr match hello e
0

$ expr match hello 'h.*o'
5

$ expr match hello 'h.*l'
4

$ expr match hello 'h.*e'
2
    
por 18.04.2018 / 18:25