ドメインだけを抽出するためにsedを使用してURLの行をクリーンアップしようとしています。
だからから:
http://www.suepearson.co.uk/product/174/71/3816/
が欲しいです:
(トレーニングのスラッシュの有無にかかわらず、関係ありません)
私が試してみました:
sed 's|\(http:\/\/.*?\/\).*|\1|'
そして(欲張りでない量指定子をエスケープする)
sed 's|\(http:\/\/.*\?\/\).*|\1|'
しかし、欲張りでない量指定子が機能するようには思えないので、常に文字列全体に一致することになります。
基本的でも拡張されたPosix/GNU正規表現も欲張りではない数量詞を認識しません。後で正規表現が必要です。幸いなことに、このコンテキストに対するPerlの正規表現は非常に簡単に入手できます。
Perl -pe 's|(http://.*?/).*|\1|'
この特定のケースでは、欲張りでない正規表現を使わずに仕事を終わらせることができます。
[^/]*
の代わりにこの欲張りでない正規表現.*?
を試してください。
sed 's|\(http://[^/]*/\).*|\1|g'
Sedでは、通常、欲張りでない検索は、セパレータまでのセパレータ以外のものを検索することで実装します。
echo "http://www.suon.co.uk/product/1/7/3/" | sed -n 's;\(http://[^/]*\)/.*;\1;p'
出力:
http://www.suon.co.uk
これは:
-n
を出力しないs/<pattern>/<replace>/p
;
ではなく/
検索コマンド区切り文字を使用します。s;<pattern>;<replace>;p
\(
... \)
の間の一致を覚えていて、後で\1
、\2
..でアクセス可能です。http://
と一致[]
、[ab/]
の後に続くものは、a
、b
、または/
のいずれかを意味します。^
の最初の[]
はnot
を意味するので、[]
内のもの以外のものが続きます。[^/]
は/
文字以外の何かを意味します*
は前のグループを繰り返すため、[^/]*
は/
以外の文字を意味します。sed -n 's;\(http://[^/]*\)
は検索してhttp://
に続く/
以外の任意の文字で覚えていることを意味し、あなたが見つけたものを覚えていますsed -n 's;\(http://[^/]*\)/'
しかし、/
を追加するので、ドメインの終わりまで検索したいので、次の/
で停止し、最後に別の.*
を追加します。\1
)がドメインになったので、マッチした行をグループ\1
に保存されているもので置き換え、print:sed -n 's;\(http://[^/]*\)/.*;\1;p'
ドメインの後に円記号を含める場合は、覚えておくためにグループに円記号をもう1つ追加します。
echo "http://www.suon.co.uk/product/1/7/3/" | sed -n 's;\(http://[^/]*/\).*;\1;p'
出力:
http://www.suon.co.uk/
sedは "欲張りでない"演算子をサポートしません。
"/"を一致から除外するには、 "[]"演算子を使用する必要があります。
sed 's,\(http://[^/]*\)/.*,\1,'
P.S "/"をバックスラッシュする必要はありません。
sed
の遅延(非欲張り)量指定子のシミュレーションそして他のすべての正規表現フレーバー!
式の最初の出現を見つける:
POSIX ERE(-r
オプションを使用)
正規表現:
(EXPRESSION).*|.
セッド:
sed -r "s/(EXPRESSION).*|./\1/g" # Global `g` modifier should be on
例(最初の数字列を見つける)ライブデモ:
$ sed -r "s/([0-9]+).*|./\1/g" <<< "foo 12 bar 34"
12
どのように機能しますか?
この正規表現は、代替|
から恩恵を受けます。各位置で、エンジンは代替の最初の側(ターゲット)を探し、それが一致しない場合、ドットのある代替の2番目の側.
は次の即時文字に一致します。
グローバルフラグが設定されているため、エンジンは入力文字列またはターゲットの最後まで文字ごとに一致を継続しようとします。交替の左側の最初で唯一のキャプチャグループが一致するとすぐに(EXPRESSION)
行の残りもすぐに消費されます.*
。現在、最初のキャプチャグループで価値を保持しています。
POSIX BRE
正規表現:
\(\(\(EXPRESSION\).*\)*.\)*
セッド:
sed "s/\(\(\(EXPRESSION\).*\)*.\)*/\3/"
例(最初の数字列を見つける):
$ sed "s/\(\(\([0-9]\{1,\}\).*\)*.\)*/\3/" <<< "foo 12 bar 34"
12
これはEREバージョンに似ていますが、交互に関係しません。それで全部です。各単一位置で、エンジンは数字の照合を試みます。
見つかった場合、後続のその他の数字が消費されてキャプチャされ、*
はmoreまたはzeroを意味するため、残りの行はすぐに一致します。2番目のキャプチャグループ\(\([0-9]\{1,\}\).*\)*
ドット.
に到達して単一の文字に一致し、このプロセスが続行されます。
delimited式の最初の出現を見つける:
このアプローチは、区切られた文字列の最初の出現に一致します。文字列のブロックと呼ぶことができます。
sed "s/\(END-DELIMITER-EXPRESSION\).*/\1/; \
s/\(\(START-DELIMITER-EXPRESSION.*\)*.\)*/\1/g"
入力文字列:
foobar start block #1 end barfoo start block #2 end
-EDE:end
-SDE:start
$ sed "s/\(end\).*/\1/; s/\(\(start.*\)*.\)*/\1/g"
出力:
start block #1 end
最初の正規表現\(end\).*
は、最初の終了区切り文字end
に一致してキャプチャし、置換はすべて、最後の区切り文字である最近キャプチャされた文字と一致します。この段階での出力はfoobar start block #1 end
です。
次に、上記のPOSIX BREバージョンと同じ2番目の正規表現\(\(start.*\)*.\)*
に結果が渡されます。開始区切り文字start
が一致しない場合は単一の文字に一致し、そうでない場合は開始区切り文字に一致してキャプチャし、残りの文字に一致します。
アプローチ2(区切り式)を使用して、2つの適切な式を選択する必要があります。
EDE:[^:/]\/
SDE:http:
使用法:
$ sed "s/\([^:/]\/\).*/\1/g; s/\(\(http:.*\)*.\)*/\1/" <<< "http://www.suepearson.co.uk/product/174/71/3816/"
出力:
http://www.suepearson.co.uk/
このスレッドは本当に古いですが、私は人々がまだそれを必要としていると思います。最初に出現したHELLO
までのすべてを殺したいとしましょう。 [^HELLO]
...と言うことはできません。
そこで、top_sekrit
のように、入力に期待していないユニークなWordを捨てることができると仮定して、Niceソリューションには2つのステップがあります。
この場合、次のことができます。
s/HELLO/top_sekrit/ #will only replace the very first occurrence
s/.*top_sekrit// #kill everything till end of the first HELLO
もちろん、もっと単純な入力では、もっと小さなWord、あるいはたぶん1つの文字を使うことができます。
HTH!
これはcutを使って行うことができます。
echo "http://www.suepearson.co.uk/product/174/71/3816/" | cut -d'/' -f1-3
sed - Christoph Sieghartによる貪欲なマッチング
Sedで欲張りでない一致を得るための秘訣は、一致を終わらせるものを除くすべての文字に一致することです。非常に簡単ですが、貴重な時間を無駄にしてしまいました。Shellスクリプトは、結局のところ、すばやく簡単に実行できるはずです。だから誰かがそれを必要とするかもしれない場合には:
貪欲マッチング
% echo "<b>foo</b>bar" | sed 's/<.*>//g'
bar
欲張りでないマッチング
% echo "<b>foo</b>bar" | sed 's/<[^>]*>//g'
foobar
正規表現を使わない別の方法は、fields/delimiterメソッドを使うことです。
string="http://www.suepearson.co.uk/product/174/71/3816/"
echo $string | awk -F"/" '{print $1,$2,$3}' OFS="/"
sed
は確かにその場所を持っていますが、これはそれらの1つではありません!
Deeが指摘したように、cut
を使うだけです。この場合、はるかに簡単ではるかに安全です。これは、Bash構文を使用してURLからさまざまなコンポーネントを抽出する例です。
url="http://www.suepearson.co.uk/product/174/71/3816/"
protocol=$(echo "$url" | cut -d':' -f1)
Host=$(echo "$url" | cut -d'/' -f3)
urlhost=$(echo "$url" | cut -d'/' -f1-3)
urlpath=$(echo "$url" | cut -d'/' -f4-)
あなたにあげる:
protocol = "http"
Host = "www.suepearson.co.uk"
urlhost = "http://www.suepearson.co.uk"
urlpath = "product/174/71/3816/"
ご覧のとおり、これはもっと柔軟なアプローチです。
(Deeの全クレジット)
純粋な(GNU)sedを使用してこれを解決するという希望はまだあります。これにもかかわらず、これは一般的な解決策ではありませんが、次のように文字列の不要な部分をすべて排除するために「ループ」を使用できます。
sed -r -e ":loop" -e 's|(http://.+)/.*|\1|' -e "t loop"
ここでの唯一の問題は、最後の区切り文字( '/')も切り捨てることですが、本当に必要な場合は、「ループ」が終了した後で単純に元に戻すことができます。コマンドライン:
-e "s,$,/,"
sed 's|(http:\/\/[^\/]+\/).*|\1|'
sed -Eは正規表現を拡張された(現代の)正規表現として解釈します
更新:MacOS Xでは-E、GNU sedでは-r。
特にPerlやcutなどの代わりにsedを使用しようとしていると述べたので、グループ化してみてください。これにより、欲張りでない識別子が認識されない可能性があります。最初のグループはプロトコルです(すなわち、 'http://'、 'https://'、 'tcp://'など)。 2番目のグループはドメインです。
echo "http://www.suon.co.uk/product/1/7/3/" | sed "s | ^ \(。* // \)\([^ /] * \)。* $ |\1\2 |"
グループ化に慣れていない場合は、ここから始めてください。
これは、sedを使用して複数文字ストリングの非欲張りなマッチングを堅牢に実行する方法です。たとえば次の入力のように、すべてのfoo...bar
を<foo...bar>
に変更したいとしましょう。
$ cat file
ABC foo DEF bar GHI foo KLM bar NOP foo QRS bar TUV
この出力になるはずです:
ABC <foo DEF bar> GHI <foo KLM bar> NOP <foo QRS bar> TUV
これを行うには、fooとbarを個々の文字に変換してから、それらの間のそれらの文字の否定を使用します。
$ sed 's/@/@A/g; s/{/@B/g; s/}/@C/g; s/foo/{/g; s/bar/}/g; s/{[^{}]*}/<&>/g; s/}/bar/g; s/{/foo/g; s/@C/}/g; s/@B/{/g; s/@A/@/g' file
ABC <foo DEF bar> GHI <foo KLM bar> NOP <foo QRS bar> TUV
上記では:
s/@/@A/g; s/{/@B/g; s/}/@C/g
は{
と}
を入力に存在できないプレースホルダー文字列に変換しているので、それらの文字はfoo
とbar
に変換するのに利用できます。s/foo/{/g; s/bar/}/g
はfoo
とbar
をそれぞれ{
と}
に変換していますs/{[^{}]*}/<&>/g
が欲しい操作を実行しています - foo...bar
を<foo...bar>
に変換するs/}/bar/g; s/{/foo/g
は{
と}
をfoo
とbar
に変換しています。s/@C/}/g; s/@B/{/g; s/@A/@/g
は、プレースホルダー文字列を元の文字に変換しています。最初のステップでそのような文字列を作成するので、入力に含まれていない特定の文字列には依存しません。また、{[^{}]*}
を何回でも使用できるので、一致する特定の正規表現の出現箇所には関係ありません。あなたが欲しい実際のマッチを分離するためにそして/またはseds数値マッチ演算子で、式の中で必要です。 2回目だけを置き換える
$ sed 's/@/@A/g; s/{/@B/g; s/}/@C/g; s/foo/{/g; s/bar/}/g; s/{[^{}]*}/<&>/2; s/}/bar/g; s/{/foo/g; s/@C/}/g; s/@B/{/g; s/@A/@/g' file
ABC foo DEF bar GHI <foo KLM bar> NOP foo QRS bar TUV
私はこれが古いエントリであることを認識していますが、誰かがそれを役に立つと思うかもしれません。完全なドメイン名は253文字を超えないようにしてください。。*を。\ {1、255 \}に置き換えます。
まだこの答えを見たことがないので、vi
またはvim
を使ってこれを実行する方法を次に示します。
vi -c '%s/\(http:\/\/.\{-}\/\).*/\1/ge | wq' file &>/dev/null
これはvi
:%s
置換をグローバルに実行し(末尾のg
)、パターンが見つからない場合(e
)にエラーを発生させないようにして、結果の変更をディスクに保存して終了します。 &>/dev/null
はGUIが画面上で短く点滅するのを防ぎます。
私はvi
を超複雑な正規表現に使うことが好きです。 デッド (2)vimは非常に高度な正規表現エンジンを持っています、そして(3)私はすでにvi
正規表現に精通しています。日用量編集文書。
echo "/home/one/two/three/myfile.txt" | sed 's|\(.*\)/.*|\1|'
気にしないで、私は別のフォーラムでそれを得た:)
別のsedのバージョン:
sed 's|/[:alphanum:].*||' file.txt
これは/
の後に英数字が続き(したがって、他のスラッシュはいけません)、行末までの残りの文字と一致します。その後それは何もしないでそれを置き換えます(すなわちそれを削除します)。
sed 's|\(http:\/\/www\.[a-z.0-9]*\/\).*|\1|
も動きます
これが2段階のアプローチとawkでできることです。
A=http://www.suepearson.co.uk/product/174/71/3816/
echo $A|awk '
{
var=gensub(///,"||",3,$0) ;
sub(/\|\|.*/,"",var);
print var
}'
それが役立つことを願っています!