Назад | Перейти на главную страницу

Самый простой способ извлечения подстроки в оболочке Unix?

Какой самый простой способ извлечь подстроку в оболочке Unix (с помощью регулярного выражения)?

Простые средства:

Обновить

Я понял, что само регулярное выражение противоречит простоте, и выбрал самое простое. cut как выбранный ответ. Прошу прощения за расплывчатый вопрос. Я изменил заголовок, чтобы точнее представить текущее состояние этого QA.

cut может быть полезно:

$ 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 Builtins тоже хороши для этого, вот пример скрипта:

#!/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})"

Это выводит:

  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)

И, как указано в Gnudif выше, всегда есть sed / awk / perl, когда дела идут действительно тяжело.

Учтите также /usr/bin/expr.

$ expr substr hello 2 3
ell

Вы также можете сопоставить шаблоны с началом строк.

$ 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

Оболочки Unix традиционно не имеют встроенной поддержки регулярных выражений. Bash и Zsh работают, поэтому, если вы используете =~ оператор для сравнения строки с регулярным выражением, затем:

Вы можете получить подстроки из $BASH_REMATCH массив в bash.

В Zsh, если BASH_REMATCH параметр оболочки установлен, значение находится в $BASH_REMATCH массив, иначе он в $MATCH/$match связанная пара переменных (одна скалярная, другая - массив). Если RE_MATCH_PCRE задана опция, тогда используется механизм PCRE, иначе системные библиотеки регулярных выражений для соответствия расширенному синтаксису регулярных выражений согласно bash.

Итак, самое простое: если вы используете bash:

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

Если вы не используете Bash или Zsh, все становится сложнее, так как вам нужно использовать внешние команды.

Скорее всего, вам нужны инструменты grep и sed, в зависимости от структуры текста.

sed должен помочь, если вы не знаете, что это за подстрока, но знаете какой-то шаблон, связанный с ней.

например, если вы хотите найти подстроку цифр, которая начинается со знака «#», вы можете написать что-то вроде:

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

grep мог бы сделать что-то подобное, но вопрос в том, что вам нужно делать с подстрокой и говорим ли мы о обычном тексте с разделителями в конце строки или нет.