web-dev-qa-db-fra.com

Un moyen simple d'extraire la sous-chaîne dans une coquille UNIX?

Quel est le moyen le plus simple d'extraire la sous-chaîne sur une coquille UNIX (avec regex)?

Moyen simple:

  • moins de fonctionnalités
  • moins d'options
  • moins d'étude

Mise à jour

J'ai réalisé que la regex elle-même est conflictuelle avec la simplicité et j'ai choisi le plus simple cut comme réponse choisie. Je suis désolé pour une vague question. J'ai changé de titre pour représenter plus précisément l'état actuel de ce QA.

8
Eonil

cut pourrait être utile:

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

Shell Construits sont bons pour cela aussi, voici un exemple 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})"

Qui sorties:

  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)

Et comme selon Gnudi ci-dessus, il y a toujours SED/AWK/PERL pour que la situation soit vraiment difficile.

12
davey

Considérer aussi /usr/bin/expr.

$ expr substr hello 2 3
ell

Vous pouvez également correspondre aux modèles contre le début des chaînes.

$ 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
3
mpb

Les coquilles UNIX ne disposent pas traditionnellement du support de regex intégré. Bash et ZSH font les deux, donc si vous utilisez le =~ Opérateur de comparer une chaîne à une regex, puis:

Vous pouvez obtenir les sous-chaînes du $BASH_REMATCH Array dans Bash.

Dans ZSH, si le BASH_REMATCH L'option Shell est définie, la valeur est dans le $BASH_REMATCH Array, sinon c'est dans le $MATCH/$match Paire de variables liées (un scalaire, l'autre un tableau). Si la RE_MATCH_PCRE L'option est définie, puis le moteur PCRE est utilisé, sinon les bibliothèques système Regexp, pour une correspondance de la syntaxe Regexp étendue, selon Bash.

Donc, le plus simplement: si vous utilisez bash:

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

Si vous n'utilisez pas Bash ou ZSH, il devient plus compliqué car vous devez utiliser des commandes externes.

2
Phil P

grep et SED sont probablement les outils que vous souhaitez, en fonction de la structure du texte.

sED devrait faire l'affaire, si vous ne savez pas ce que la sous-chaîne est, mais connaissez un modèle qui l'entoure.

par exemple, si vous souhaitez trouver une sous-chaîne de chiffres qui commence par un signe "#", vous pouvez écrire quelque chose comme:

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

gREP pourrait faire quelque chose de similaire, mais la question est de savoir ce que vous devez faire avec la sous-chaîne et si nous parlons du texte délimité de la ligne de ligne normale ou non.

2
Gnudiff