
問題は、csvファイルの1列に1つ以上のEメールアドレスがあることです。出力には各メールアドレスに1行が必要です。各電子メールアドレスに対して行を繰り返すために電子メールアドレスに対してforループを実行するにはどうすればよいですか?正規表現を使用して2番目の列のすべての電子メールアドレスを見つけて、配列を繰り返すとします。しかし、すべての電子メールを配列にインポートするにはどうすればよいですか?
これは単純なawkスクリプトです:
BEGIN {
FPAT = "([^,]*)|(\"[^\"]+\")"
OFS=","
}
{
name=substr($1,2,length($1)-2)
email=substr($2,2,length($2)-2)
print name, email
}
入力する:
"agrippa","[email protected]"
"elvirka","[email protected]"
"Inofs","[email protected];[email protected]"
"bekbz","[email protected],[email protected]"
"njkzif","[email protected]|[email protected]"
"njycz","[email protected]:[email protected]"
"DanielEdict","[email protected]"
"JosEmbesy","[email protected] , [email protected]"
"Walterdon","[email protected] ; [email protected]"
"Kennethlob","[email protected]"
"Ninosh","[email protected]"
"Patrickbam","[email protected]"
希望の出力:
agrippa,[email protected]
elvirka,[email protected]
Inofs,[email protected]
Inofs,[email protected]
bekbz,[email protected]
bekbz,[email protected]
njkzif,[email protected]
njkzif,[email protected]
njycz,[email protected]
njycz,[email protected]
DanielEdict,[email protected]
JosEmbesy,[email protected]
JosEmbesy,[email protected]
Walterdon,[email protected]
Walterdon,[email protected]
Kennethlob,[email protected]
Ninosh,[email protected]
Patrickbam,[email protected]
実際のデータの詳細については、これは2つの列ではありません。実際の入力データのヘッダーは次のとおりです。
"Created","first name","last name","address1","address2","city","state","zip","country","phone Office","phone Cell","phone Home","company Name","webSite","email","NoEmail","License Type","Issued Date","License Expires"
出力は2つの列ではなく、電子メールは現在の出力の最新の項目ではありませんが、必要に応じて行うことができます。
入力データのもう一つの点は、それがCSVファイルであり、すべてのデータに引用符があることです。ただし、データがない場合は引用符はありません。 FPATは、部分文字列を使用して削除する各列の周りの引用符を除いて、うまく処理するようです。
実際の入力の例は次のとおりです。
"9/1/2019","Can","Back","77 High Drive","","Chicago","IL","45099","USA","555-555-8521",,,"company name","http://www.yourcomapny.co.uk/","[email protected],[email protected]","","foobar","9/1/2019","9/1/2020"
答え1
GNU awkを使用するFPAT
(すでにgawkが必要なので、gensub()
略語\s
も使用[[:space:]]
):
$ cat tst.awk
BEGIN {
FPAT = "([^,]*)|(\"[^\"]+\")"
OFS=","
}
{
name = gensub(/^"|"$/,"","g",$1)
n = split(gensub(/^"|"$/,"","g",$2),emails,/\s*[;,|:]\s*/)
for (i=1; i<=n; i++) {
print name, emails[i]
}
}
$
$ awk -f tst.awk file
agrippa,[email protected]
elvirka,[email protected]
Inofs,[email protected]
Inofs,[email protected]
bekbz,[email protected]
bekbz,[email protected]
njkzif,[email protected]
njkzif,[email protected]
njycz,[email protected]
njycz,[email protected]
DanielEdict,[email protected]
JosEmbesy,[email protected]
JosEmbesy,[email protected]
Walterdon,[email protected]
Walterdon,[email protected]
Kennethlob,[email protected]
Ninosh,[email protected]
Patrickbam,[email protected]
FWIW私は通常、この*sub(/^"|"$/,"",...)
方法を使用してCSVフィールドから可能な先行/訓練二重引用符を削除します。substr()
二重引用符なしでフィールドを分割しない方法に比べて利点があるためです。
[;,|:]
電子メールアドレスが破損しているか、または処理を忘れたもの(たとえば、の区切り文字)に備えて、いくつかのエラー検出を追加することもできます。
$ cat tst.awk
BEGIN {
FPAT = "([^,]*)|(\"[^\"]+\")"
OFS=","
}
{
name = gensub(/^"|"$/,"","g",$1)
n = split(gensub(/^"|"$/,"","g",$2),emails,/\s*[;,|:]\s*/)
for (i=1; i<=n; i++) {
email = emails[i]
if ( gsub(/@/,"&",email) != 1 ) {
printf "ERROR: too few or too many email addresses in \"%s\"\n", email | "cat>&2"
exit 1
}
print name, email
}
}
本当に電子メールアドレスを確認したい場合は、FWIW過去5年間に問題がなく、この正規表現の修正版を使用してきたことを知っています。http://www.regular-expressions.info/email.html(私は特に[:alpha:]の代わりに[a-zA-Z]を使用しました。なぜなら私は私のロケールでそのように見なされる文字だけを許可したいからです。アプリケーションに適した文字を決定するのはあなたの役割です)。
(email ~ /^[0-9a-zA-Z._%+-]+@[0-9a-zA-Z.-]+\.[a-zA-Z]{2,}$/)
答え2
15以上の列と7列の括弧内の説明はよくわかりませんが、与えられた例では次のことを試してみてください。
awk -F, '
{gsub (/[" ]/,_) # remove double quotes and space all over
D1 = $1 # save field 1 and
sub ($1 FS, _) # remove it from line
n = split ($0, T, /[,;:\|]/) # split the residual line into array T
for (i=1; i<=n; i++) print D1, T[i] # print former $1, and each T element
}
' OFS=, file
agrippa,[email protected]
elvirka,[email protected]
Inofs,[email protected]
Inofs,[email protected]
.
.
.
Patrickbam,[email protected]