Linux - ""の間の特殊文字を無視する方法は?

Linux - ""の間の特殊文字を無視する方法は?

私のファイル:(1本のサンプルライン)

MMP,"01_janitorial,02_cleaning_tools",1,,CUBIC_INCH,"(14) tray capacity, 6" upright with 3" spacing, mounts on 48"W x 24"D, taupe epoxy, fits MetroMax i
& MetroMax Q shelf, NSF",CLEANING

これを7つの列を持つPostgresqlテーブルに読み込む必要があります。

熱分析:

  1. MMP
  2. "01_janitorial,02_cleaning_tools"
  3. 1
  4. CUBIC_INCH
  5. "(14) tray capacity, 6" upright with 3" spacing, mounts on 48"W x 1. 24"D, taupe epoxy, fits MetroMax i & MetroMax Q shelf, NSF"
  6. CLEANING

ファイルはデフォルトでコンマで区切られていますが、テキストが二重引用符内にある場合は、カンマ、キャリッジリターン(存在する場合)、二重引用符を無視する必要があります。 2列と6列に示す通りです。

postgresqlコピーコマンドを使用してロードするか、awk、perl、sed、またはその他のコマンドを使用してファイルを変換してロードできます。

答え1

言ったように、ファイルが誤って生成されました。ただし、,区切り文字だけでなく、を使用して",問題を解決することもできます,"。もちろん、カスタムスクリプトが必要であり、6番目のフィールドで同様の状況が発生しないという保証はありません。

または、6番目のフィールドが唯一の破損したフィールドであると仮定し、最初の5つのフィールドを削除してから、結果から最後のフィールドとカンマを削除することもできます。残りはゲーム6コンテンツです。

答え2

通常、単独では-F,CSVファイルを解析するのに十分ではありません。特に説明されているように、区切り文字が引用符付き文字列の一部である可能性がある場合はさらにそうです。あなたはそれを解決することができます一部FPATフィールド区切り文字の文字を定義するのではなく、式を使用してフィールドを定義するawkと、1行ずつ移動するため、最初にデータで改行を使用する必要があります。

完了したら、次のことができますawk 'BEGIN {FPAT="([^,]+)|(\"[^\"]+\")"} { /* normal processing here */ }' /path/to/file

式は、フィールドを「カンマ以外のすべての項目」または「二重引用符、二重引用符以外の1つ以上の項目、後に二重引用符が続く項目」として定義します。

しかし、データを参照すると爆発します。彼ら自身二重引用符が含まれています。

答え3

引用符が正しくエスケープされないため、ソリューションはデータファイルに非常に具体的です。グリッチバーが1つしかないので、これはかなり可能です。あなたのため:

#!/bin/bash
while IFS='' read -r line || [[ -n "$line" ]]; do
    echo "Line: $line"

# grabbing the first field is easy ..
    f1=$(echo $line | cut -d, -f1 )

# now remove the first field from the line
    line=$(echo $line | sed "s/$f1,//" )
    echo "Line is now: $line"

# to grab the second field use quote as a delimiter
    f2=$(echo $line | cut -d\" -f2 )

# now remove the second field from the line
    line=$(echo $line | sed "s/\"$f2\",//" )
    echo "Line is now: $line"

# fields 3,4,5 are trivial .. just repeat the same pattern as 1 and then remove them
    f3=$(echo $line | cut -d, -f1 )
    line=$(echo $line | sed "s/$f3,//" )
    echo "Line is now: $line"
    f4=$(echo $line | cut -d, -f1 )
    line=$(echo $line | sed "s/$f4,//" )
    echo "Line is now: $line"
    f5=$(echo $line | cut -d, -f1 )
    line=$(echo $line | sed "s/$f5,//" )

# here is the "trick" ... reverse the string, then you can cut field 7 first!
    line=$(echo $line | rev)
    echo "Line is now: $line"
    f7=$(echo $line | cut -d, -f1 )

# now remove field 7 from the string, then reverse it back
    line=$(echo $line | sed "s/$f7,//" )
    f7=$(echo $f7 | rev)

# now we can reverse the remaining string, which is field 6 back to normal
    line=$(echo $line | rev)
# and then remove the leading quote
    line=$(echo $line | cut --complement -c 1)
# and then remove the trailing quote
    line=$(echo $line | sed "s/\"$//" )
    echo "Line is now: $line"
# and then double up all the remaining quotes
    f6=$(echo $line | sed "s/\"/\"\"/g" )

    echo f1 = $f1
    echo f2 = $f2
    echo f3 = $f3
    echo f4 = $f4
    echo f5 = $f5
    echo f6 = $f6
    echo f7 = $f7
    echo $f1,\"$f2\",$f3,$f4,$f5,\"$f6\",$f7 >> fixed.txt
done < "$1"

どのように動作するかを示すために、多くの出力をエコーするようにしました。理解したら、すべてのエコードアを削除してより速くすることができます。固定行を次に追加します。固定.txt

以下は実行と出力の例です。

[root@alpha ~]# ./fixit.sh test.txt
Line: MMP,"01_janitorial,02_cleaning_tools",1,,CUBIC_INCH,"(14) tray capacity, 6" upright with 3" spacing, mounts on 48"W x 24"D, taupe epoxy, fits MetroMax i & MetroMax Q shelf, NSF",CLEANING
Line is now: "01_janitorial,02_cleaning_tools",1,,CUBIC_INCH,"(14) tray capacity, 6" upright with 3" spacing, mounts on 48"W x 24"D, taupe epoxy, fits MetroMax i & MetroMax Q shelf, NSF",CLEANING
Line is now: 1,,CUBIC_INCH,"(14) tray capacity, 6" upright with 3" spacing, mounts on 48"W x 24"D, taupe epoxy, fits MetroMax i & MetroMax Q shelf, NSF",CLEANING
Line is now: ,CUBIC_INCH,"(14) tray capacity, 6" upright with 3" spacing, mounts on 48"W x 24"D, taupe epoxy, fits MetroMax i & MetroMax Q shelf, NSF",CLEANING
Line is now: CUBIC_INCH,"(14) tray capacity, 6" upright with 3" spacing, mounts on 48"W x 24"D, taupe epoxy, fits MetroMax i & MetroMax Q shelf, NSF",CLEANING
Line is now: GNINAELC,"FSN ,flehs Q xaMorteM & i xaMorteM stif ,yxope epuat ,D"42 x W"84 no stnuom ,gnicaps "3 htiw thgirpu "6 ,yticapac yart )41("
Line is now: (14) tray capacity, 6" upright with 3" spacing, mounts on 48"W x 24"D, taupe epoxy, fits MetroMax i & MetroMax Q shelf, NSF
f1 = MMP
f2 = 01_janitorial,02_cleaning_tools
f3 = 1
f4 =
f5 = CUBIC_INCH
f6 = (14) tray capacity, 6"" upright with 3"" spacing, mounts on 48""W x 24""D, taupe epoxy, fits MetroMax i & MetroMax Q shelf, NSF
f7 = CLEANING

別の方法で引用符をエスケープする必要がある場合は、上記を見ると非常に明白です。

答え4

参照ファイルからキャリッジリターンを削除して最終製品を入手しました。スクリプトは次のとおりです。

$ cat remove_cr.awk
#!/usr/bin/awk -f
{ record = record $0
  # If number of quotes is odd, continue reading record.
  if ( gsub( /"/, "&", record ) % 2 )
  { record = record " "
    next
  }
}
{ print record
  record = ""
}

関連情報