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
シェルビルトインもこれに適しています。ここにサンプルスクリプトを示します。
#!/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の$BASH_REMATCH
配列から部分文字列を取得できます。
Zshでは、BASH_REMATCH
シェルオプションが設定されている場合、値は$BASH_REMATCH
配列にあります。それ以外の場合は、$MATCH/$match
タイ変数ペアにあります(1つのスカラー、もう1つの配列)。 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も同様の処理を実行できますが、問題は、部分文字列をどのように処理する必要があるか、および通常の行末区切りテキストを使用しているかどうかです。