
7つのフィールドを含むカンマ区切りのファイルがあります。ただし、これらのフィールドの 1 つが ,
値に含まれます。|
でファイルを変更せずにファイル区切り記号をに変更したいと思います,
。
私が持っているファイル:
Name,Age,Country,ID,Address,Category,DOB
John Doe,19,England,3653,Manchester, England,Main Worker,20-05-1995
希望の出力:
Name,Age,Country,ID,Address,Category,DOB
John Doe|19|England|3653|Manchester, England|Part Time Worker|20-05-1995
いくつかの解決策を試しましたが、欲しいものを達成できませんでした。最初の4列の区切り文字のみを更新する次のコマンドを試しました。
sed 's/,/|/;s/,/|/;s/,/|/;s/,/|/' file
私が探しているのは、最初の4列と最後の2列の区切り文字を更新することです。これにより、アドレス列を変更せずに区切られたファイルを更新できます。
以下のコードを思い出しましたが、これを行うと、,
の間の内容が削除されます。Manchester
England
awk '{ORS="";N=split($0,a,",");\
print a[1]"|"a[2]"|"a[3]"|"a[4]"|"; \
for(i=5;i<N-1;i++) print a[i];
print "|"a[N-1]"|"a[N] }'
答え1
あなたはawk
試すことができます:
awk -F, -v OFS='|' 'NR==1{print $0} NR>1{$5 = $5 FS $6; print $1,$2,$3,$4,$5,$7,$8}' file
Name,Age,Country,ID,Address,Category,DOB
John Doe|19|England|3653|Manchester, England|Main Worker|20-05-1995
答え2
bashを使用すると、アドレスフィールドのコンマ数に関係なくこれを処理できます。
# function to join strings with a separator
join() {
local IFS=$1
shift
printf '%s\n' "$*"
}
# process the file
{
IFS=, read -ra header
join '|' "${header[@]}"
f=${#header[@]} # expected num of fields
while IFS=, read -ra row; do
n=${#row[@]} # actual num
# with a placeholder for the address
real_row=("${row[@]:0:4}" __ "${row[@]:n-2}")
# set the actual address
real_row[4]=$(join ',' "${row[@]:4:n-f+1}")
join '|' "${real_row[@]}"
done
} < file
出力
Name|Age|Country|ID|Address|Category|DOB
John Doe|19|England|3653|Manchester, England|Main Worker|20-05-1995
答え3
どのコンマを維持し、どのように変更する必要があるかをどのように知っているか説明しませんでした。提供した単一の例行に基づいて、スペースの後ろ,
のすべてを次のように置き換えます|
。
$ sed -E 's/,(\S)/\|\1/g' file
Name|Age|Country|ID|Address|Category|DOB
John Doe|19|England|3653|Manchester, England|Main Worker|20-05-1995
またはタイトルを変更したくない場合:
$ sed -E '2,${s/,(\S)/\|\1/g}' file
Name,Age,Country,ID,Address,Category,DOB
John Doe|19|England|3653|Manchester, England|Main Worker|20-05-1995
または、スペースに依存できず、代わりに5番目のカンマ以外の行のすべてのコンマを次のように置き換える必要がある場合はどうなりますか? 「この行に7つ以上のフィールドがある場合は、,
この行の5番目のフィールドを一部として処理されたものに置き換えます。4番目のフィールドであり、区切り文字としては使用されません。」もしそうなら、次のことが役に立ちます。
$ $ perl -F, -lane 'if($#F>6){$F[4].=",$F[5]"; splice(@F,5,1)} print join("|",@F)' file
Name|Age|Country|ID|Address|Category|DOB
John Doe|19|England|3653|Manchester, England|Main Worker|20-05-1995
または、ヘッダーを変更したくない場合は、次のようにします。
$ perl -F, -lane 'if($#F>6){$F[4].=",$F[5]"; splice(@F,5,1)} $.==1 ? print : print join("|",@F)' file
Name,Age,Country,ID,Address,Category,DOB
John Doe|19|England|3653|Manchester, England|Main Worker|20-05-1995
答え4
$ perl -F, -lne 'if ($#F == 7) {$F[4] .= ",$F[5]"; splice @F,5,1};
print join("|",@F);' input.csv
Name|Age|Country|ID|Address|Category|DOB
John Doe|19|England|3653|Manchester, England|Main Worker|20-05-1995
この perl one-liner は、各入力行にカンマ区切りのフィールドがいくつあるかを確認します。 8つのフィールドがある場合は、フィールド4にカンマとフィールド5の内容を追加してから、フィールド5を削除しますsplice()
。
@F
Perlを使用または呼び出すときは、awkの$ 1、$ 2、$ 3などに対応する自動分割配列を使用して、これをすべて行います。-F
-a
|
次に、フィールド4と5を変更したかどうかに関係なく、パイプ文字で連結された@ F配列を印刷します。
注:Perl配列は1ではなく0から始まります。$#F
@F配列の最後のインデックス番号を返すので、== 7
テストではありません== 8
。 8つのフィールドを持つレコードでは、@ Fのインデックスは0..7です。これはまた、5番目のフィールド(アドレス)$F[4]
がではなく呼び出されるという意味でもあります$F[5]
。