211

私はこの例を見てきました:

hello=ho02123ware38384you443d34o3434ingtod38384day
echo ${hello//[0-9]/}

次の構文に従います。${variable//pattern/replacement}

残念ながら、patternフィールドは完全な正規表現構文をサポートしていないようです (たとえば、.orを使用すると、リテラル文字と一致しようとします)。\s

完全な正規表現構文を使用して文字列を検索/置換するにはどうすればよいですか?

4

9 に答える 9

203

sedを使用します。

MYVAR=ho02123ware38384you443d34o3434ingtod38384day
echo "$MYVAR" | sed -e 's/[a-zA-Z]/X/g' -e 's/[0-9]/N/g'
# prints XXNNNNNXXXXNNNNNXXXNNNXNNXNNNNXXXXXXNNNNNXXX

後続-eの は順番に処理されることに注意してください。また、g式のフラグは、入力内のすべての出現に一致します。

この方法を使用して、お気に入りのツールを選択することもできます。つまり、perl、awk などです。

echo "$MYVAR" | perl -pe 's/[a-zA-Z]/X/g and s/[0-9]/N/g'

これにより、よりクリエイティブなマッチングが可能になる場合があります...たとえば、上記のスニップでは、最初の式が一致しない限り、数値置換は使用されません (遅延and評価のため)。そしてもちろん、Perl の完全な言語サポートにより、入札を行うことができます...

于 2012-10-24T05:16:53.663 に答える
121

これらの例は、sed を使用する必要のない bash でも機能します。

#!/bin/bash
MYVAR=ho02123ware38384you443d34o3434ingtod38384day
MYVAR=${MYVAR//[a-zA-Z]/X} 
echo ${MYVAR//[0-9]/N}

文字クラスのブラケット式も使用できます

#!/bin/bash
MYVAR=ho02123ware38384you443d34o3434ingtod38384day
MYVAR=${MYVAR//[[:alpha:]]/X} 
echo ${MYVAR//[[:digit:]]/N}

出力

XXNNNNNXXXXNNNNNXXXNNNXNNXNNNNXXXXXXNNNNNXXX

ただし、@Lanaru が知りたかったのは、質問を正しく理解していれば、「フル」または PCRE 拡張機能\s\S\w\W\d\Dなどが php ruby​​ python などでサポートされているように機能しない理由です。これらの拡張機能は、Perl 互換の正規表現 (PCRE) からのものであり、他の形式のシェル ベースの正規表現とは互換性がない場合があります。

これらは機能しません:

#!/bin/bash
hello=ho02123ware38384you443d34o3434ingtod38384day
echo ${hello//\d/}


#!/bin/bash
hello=ho02123ware38384you443d34o3434ingtod38384day
echo $hello | sed 's/\d//g'

すべてのリテラル「d」文字が削除された出力

ho02123ware38384you44334o3434ingto38384ay

しかし、以下は期待どおりに機能します

#!/bin/bash
hello=ho02123ware38384you443d34o3434ingtod38384day
echo $hello | perl -pe 's/\d//g'

出力

howareyoudoingtodday

物事がもう少し明確になることを願っていますが、まだ混乱していない場合は、REG_ENHANCED フラグが有効になっている Mac OS X でこれを試してみませんか:

#!/bin/bash
MYVAR=ho02123ware38384you443d34o3434ingtod38384day;
echo $MYVAR | grep -o -E '\d'

*nix のほとんどのフレーバーでは、次の出力のみが表示されます。

d
d
d

nJoy!

于 2014-03-07T21:48:36.263 に答える
14

繰り返し呼び出しを行っていて、パフォーマンスに関心がある場合、このテストでは、BASH メソッドが sed や他の外部プロセスに fork するよりも最大 15 倍高速であることがわかります。

hello=123456789X123456789X123456789X123456789X123456789X123456789X123456789X123456789X123456789X123456789X123456789X

P1=$(date +%s)

for i in {1..10000}
do
   echo $hello | sed s/X//g > /dev/null
done

P2=$(date +%s)
echo $[$P2-$P1]

for i in {1..10000}
do
   echo ${hello//X/} > /dev/null
done

P3=$(date +%s)
echo $[$P3-$P2]
于 2017-01-05T21:32:18.623 に答える
10

[[:digit:]]パターンとして (二重括弧に注意してください)使用します。

$ hello=ho02123ware38384you443d34o3434ingtod38384day
$ echo ${hello//[[:digit:]]/}
howareyoudoingtodday

答えを要約したかっただけです(特に@nickl-のhttps://stackoverflow.com/a/22261334/2916086)。

于 2016-08-30T02:25:26.547 に答える
0

パイソンが使えます。これは効率的ではありませんが、もう少し柔軟な構文で作業を完了できます。

ファイルに適用する

次の pythonscript は、"FROM" (ただし "notFrom" ではありません) を "TO" に置き換えます。

regex_replace.py

import sys
import re

for line in sys.stdin:
    line = re.sub(r'(?<!not)FROM', 'TO', line)
    sys.stdout.write(line)

次のように、テキストファイルに適用できます

$ cat test.txt
bla notFROM
FROM FROM
bla bla
FROM bla

bla  notFROM FROM

bla FROM
bla bla


$ cat test.txt | python regex_replace.py
bla notFROM
TO TO
bla bla
TO bla

bla  notFROM TO

bla TO
bla bla

変数に適用

#!/bin/bash

hello=ho02123ware38384you443d34o3434ingtod38384day
echo $hello

PYTHON_CODE=$(cat <<END
import sys
import re

for line in sys.stdin:
    line = re.sub(r'[0-9]', '', line)
    sys.stdout.write(line)
END
)
echo $hello | python -c "$PYTHON_CODE"

出力

ho02123ware38384you443d34o3434ingtod38384day
howareyoudoingtodday
于 2021-10-27T09:11:01.240 に答える