Какой самый простой способ извлечь подстроку в оболочке 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 мог бы сделать что-то подобное, но вопрос в том, что вам нужно делать с подстрокой и говорим ли мы о обычном тексте с разделителями в конце строки или нет.