web-dev-qa-db-ja.com

2つの異なる区切り文字でのcut / awk / sedの使用

次のような場合があります。

 [email protected]
 [email protected]
 [email protected]

私はこれらをに変換しようとしています

 [email protected]
 [email protected]
 [email protected]

したがって、最初の '_'(それを含む)から@(それを含まない)までのすべてを削除する必要があります。

私は何かを持っていますが、それは実際には正しく機能しません:

このスレッドに基づいて: 一度に2つの区切り文字に基づいてカット 、およびこのU&L Q&A: 区切り文字の最初の出現によって文字列を分割

sed 's/^.*_\([^ ]*\) .*\@\([^$]*\)$/\1 \2/' infile

しかし、運はありません。チャイムを鳴らしたい人はいますか?

2
Sten Kin

複数の@記号を使用しないと仮定すると、

sed 's/_.*@/@/' file.txt

...うまくいくはずです。

3
evilsoup

これで実際に何をしているのかわかりませんが、sedでそのように行うことができます。

$ sed 's/\(case\).*\(@test.com\)/\1\2/' 87529.txt 
[email protected]
[email protected]
[email protected]

これにより、case@の間のすべてが効果的に削除されます。

awkでも同様のことができます。

$ awk -F@ '{split($1,a,"_"); print a[1]"@"$2}' 87529.txt 

Perl(evilsoupのアプローチと同様)を使用して実行することもできます。

$ Perl -p -e 's/_.*@/@/g' 87529.txt 

または、 Perlの先読み機能 を利用できます。

$ Perl -p -e 's/_.*(?=@)//g' 87529.txt 

注:Perlの先読みと後読みを使用すると、一致する正規表現パターンに文字列を含めることができます。正規表現に対して実行される操作に含まれます。それらをキャレットの動的バージョン(^)-行の始まり、ドル($)-行の終わりと考えてください。これは、@を削除した後、追加し直すよりも少しハックが少ないです。

4
slm

行に複数の@が含まれている可能性がある場合:

sed 's/^\([^@_]*\)_[^@]*@/\1@/'

または:

awk -F@ -vOFS=@ 'NF >= 2 {sub(/_.*/,"",$1)};1'
1

シェルがパラメータ拡張をサポートしている場合は、次のようなことができます。

while read line; do
    printf "%s\n" "${line%%_*}@${line#*@}"
done < your_file_here

拡張${line%%_*}左端を削除します_およびその後のすべての拡張中${line#*@}左端を削除します@とその前のすべて。

1
Joseph R.

Evilsoup'ssolution 完璧なようです!

sedawkの両方を使用するさらに別のソリューション。

sed 's/_/ /g; s/@/ /g' file_name | awk '{ print $1"@"$NF '}

これは効率を正確に考慮しているわけではありませんが、おそらく正規表現をいじりたくない場合は簡単に理解できます。上記のコードは次のことを行います。

  • sedの最初のパターンは、「_」を空白に置き換えます。
  • sedの2番目のパターンは、「@」を空白に置き換えます。したがって、ファイルの内容を複数の列に分割します。

ケースtest.com
ケース1_2test.com
ケース1test.com

  • 最後に、awkは、分離されたコンテンツの最初と最後の列を出力するだけです。ここで、NFawkの特別な記号であり、行のフィールド数を示します。
0
Barun

ここに別のgawk方法があります:

gawk -F_ '{if(NF>1){print $1$NF} else {print $NF}}'

_をフィールド区切り文字として使用して、gawkに、複数のフィールドがある場合は最初と最後のフィールドを出力し、単一のフィールドしかない場合は最後のフィールドを出力するように指示します。

0
terdon