こんにちは、私も同様の問題があります郵便はがき
しかし、私は初めてBashに触れてファイルが少し異なるので、答えを修正してコードに適用することはできません。
複数の列(カンマで区切られたすべての列)を持つcsvファイルがあり、分割したい列は次のとおりです。 (入力ファイル)
post_id
86680728811_272953252761568
86680728811_273859942672742
86680728811_281125741936891
86680728811_10150500662053812
_86680728811_10150500969563812
86680728811_10150501303143812
86680728811_305275689511038
_86680728811_10150501624593812
86680728811_10150501873973812
86680728811_145945585518261
2番目のID番号(下線の後の番号)を抽出したいと思います。一部の列は数字で始まり、一部は空白で始まり、一部は「_」で始まることに注意してください。
私が望む出力は、それぞれ「_」で区切られたIDを含む2つの新しい列を追加することです。最初の行の例:
page ID post ID
86680728811 272953252761568
正規表現を使用して数字を読み取ろうとします。
awk -F',' '{print $2} /(?<=_)[0-9]+/' FB_Dataset.csv
しかし、これまで試したことはすべてうまくいきません。どんな提案でも役に立ちます。ありがとう
答え1
awk -F', *_?' -v OFS=, '
NR==1 {
for (i=1;i<=NF;i++) {
if ($i == "post_id") {
$i = "page ID" OFS "post ID";
col=$1;
};
};
print;
next
};
{
split($col,a,/_/);
$col=a[1] OFS a[2];
print;
};
' FB_Dataset.csv
表示されているフィールドデータが一貫性のない形式(一部はスペースで始まり、一部はアンダースコアで始まり、一部は両方)であるため、このawk
スクリプトは正規表現, *_?
(「カンマの後に0個以上のスペースが続き、オプションで後にスペースが続く」)アンダースコア ") をフィールド区切り記号 ( FS
) として使用します。
また、出力フィールド区切り記号(OFS
)をコンマに設定します。
入力を読み取ると、最初の行(CSVヘッダー)と残りのすべての行が異なるように処理されます。
最初の行(NR==1
)では、各フィールドの値を調べて文字列を見つけます"post_id"
。文字列が見つかったら、フィールド値を変更して、2つの新しいフィールド名(page ID
およびpost ID
)と後で使用できるように、OFS
フィールドのインデックス番号を変数に保存します。col
最後に変更された行を印刷します。
これは、有効なCSVファイルのフィールド名が一意であることを前提としています。複数のフィールドに名前があると正しく機能しませんpost_id
。
残りの行では、$col
下線()文字を区切り文字として使用してフィールドを配列に分割します。次に、$ colを配列の最初の2つの要素に置き換えて、変更された行を印刷します。a
_
OFS
入力例:
A,B,C,post_id,D,E,F
a,b,c,86680728811_272953252761568,d,e,f
a,b,c, 86680728811_273859942672742,d,e,f
a,b,c,86680728811_281125741936891,d,e,f
出力例:
A,B,C,page ID,post ID,D,E,F
a,b,c,86680728811,272953252761568,d,e,f
a,b,c,86680728811,273859942672742,d,e,f
a,b,c,86680728811,281125741936891,d,e,f
ヘッダー行では、このフィールドは2つのフィールド(および)post_id
に変換され、CSVデータではそのフィールドが2つのフィールドに分割されました。page ID
post ID
ただし、スクリプトはpost_id
ヘッダー行で一致するフィールド名()を取得するため、分割したいフィールドの前後のフィールド数に関係なく処理できます。このサンプルデータを使用して、4番目のフィールドに希望の名前が含まれていることを確認しました。col=4
$i
そしてawk$col
はシェルとは異なる意味を持ちます。
- シェルでは、これは次の変数を意味します。名前はい
i
、そしてcol
。 では
awk
、インデックス番号が変数値と同じフィールドの値i
(または変数col
)」です。つまり、間接参照を介してフィールドにアクセスします。たとえば、if
i=1
thenは$i
「フィールド1の値」を意味し、と同じです$1
。たとえば、フィールド番号に対して算術演算を実行する必要がある場合に便利です。 awk では、
NF
現在の入力行の最後のフィールドのインデックス番号を含む自動生成変数です。 so は$NF
「最後のフィールドの値」を意味し、$(NF-1)
「最後のフィールドの 2 番目のフィールドの値」などを意味します。
答え2
これはあなたに効果がありますか?私は次の形式を仮定します。
A B C post_id
a,b,c,86680728811_272953252761568
a,b,c, 86680728811_273859942672742
a,b,c,86680728811_281125741936891
a,b,c,86680728811_10150500662053812
a,b,c,_86680728811_10150500969563812
a,b,c,86680728811_10150501303143812
a,b,c,86680728811_305275689511038
a,b,c,_86680728811_10150501624593812
a,b,c, 86680728811_10150501873973812
a,b,c,86680728811_145945585518261
その後、コマンド
cat file | sed -Ee 's/(.*)post_id/\1page ID post I/' -e 's/,[_ ]/,/' -e 's/_/,/'
出力:
A B C page ID post ID
a,b,c,86680728811,272953252761568
a,b,c,86680728811,273859942672742
a,b,c,86680728811,281125741936891
a,b,c,86680728811,10150500662053812
a,b,c,86680728811,10150500969563812
a,b,c,86680728811,10150501303143812
a,b,c,86680728811,305275689511038
a,b,c,86680728811,10150501624593812
a,b,c,86680728811,10150501873973812
a,b,c,86680728811,145945585518261
-E
拡張正規表現(GNU)を使用すると、グループをキャプチャできます。
ヘッダーを変更してpage ID post ID
キャプチャの最初のグループ(.*)
まで追加しpost_id
、キャプチャされたグループに置き換えます\1
。page ID post ID
's/(.*)post_id/\1page ID post ID/'
_
コンマの後の行から先頭のスペースとアンダースコアを削除し、単一のコンマで置き換えます。
sed 's/,[_ ]/,/'
最後に、アンダースコアを_
カンマで置き換えます。
sed 's/_/,/'
不要なコマンドを削除しました。cut
(これは私が試した他のコマンドを思い出させます。)
答え3
私は次を使うでしょう:
awk -F' *_?' '{ print $(NF-1), $NF }' infile