特定の列の区切り文字の更新

特定の列の区切り文字の更新

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列の区切り文字を更新することです。これにより、アドレス列を変更せずに区切られたファイルを更新できます。

以下のコードを思い出しましたが、これを行うと、,の間の内容が削除されます。ManchesterEngland

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()

@FPerlを使用または呼び出すときは、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]

関連情報