Hapus hanya koma yang ada dalam tanda kutip ganda

10

Dalam file teks, saya ingin menghapus ,(koma) dan juga "(tanda kutip) (hanya jika tanda kutip ganda berisi angka yang dipisahkan oleh koma).

56,72,"12,34,54",x,y,"foo,a,b,bar"

Diharapkan ouput

56,72,123454,x,y,"foo,a,b,bar"

Catatan: Saya menunjukkan baris di atas hanya sebagai contoh. File teks saya berisi banyak baris seperti di atas dan angka yang dipisahkan oleh koma yang ada dalam tanda kutip ganda harus bervariasi. Itu adalah,

56,72,"12,34,54",x,y,"foo,a,b,bar"
56,92,"12,34",x,y,"foo,a,b,bar"
56,72,"12,34,54,78,76,54,67",x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar","12,34,54"
56,72,x,y,"foo,a,b,bar","12,34,54","45,57,84,92","bar,foo"

Output yang diharapkan:

56,72,123454,x,y,"foo,a,b,bar"
56,92,1234,x,y,"foo,a,b,bar"
56,72,12345478765467,x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar",123454
56,72,x,y,"foo,a,b,bar",123454,45578492,"bar,foo"

Ada nsejumlah angka yang ada dalam tanda kutip ganda yang dipisahkan oleh koma. Dan juga meninggalkan tanda kutip ganda yang berisi karakter apa adanya.

Saya suka sedalat pengolah teks. Saya senang jika Anda memposting sedsolusi apa pun untuk ini.

Avinash Raj
sumber
Dari 56,72,"12,34,54",x,y,"foo,a,b,bar"ke 56,72,123454,x,y,"a,b", foodan barmenghilang. Apakah itu output yang Anda inginkan?
cuonglm
Contoh yang Anda gunakan agak membingungkan karena beberapa elemen (seperti foodan bar) dihapus bersama dengan koma. Selain itu, beberapa kutipan menghilang di tempat yang lainnya. Belum lagi koma antara adan btetap juga. Apakah ada pola untuk ini?
HalosGhost
diedit teman maaf
Avinash Raj
Hasil edit Anda belum benar-benar menjelaskan contoh Anda. Silakan lihat komentar terakhir saya .
HalosGhost
hapus semua koma di dalam tanda kutip ganda dan juga tanda kutip hanya jika tanda kutip berisi angka.
Avinash Raj

Jawaban:

7

Ini (diadaptasi dari sini ) harus melakukan apa yang Anda butuhkan meskipun @Rici's Perl satu jauh lebih sederhana:

$ sed -r ':a;s/(("[0-9,]*",?)*"[0-9,]*),/\1/;ta; s/""/","/g; 
          s/"([0-9]*)",?/\1,/g ' file
56,72,123454,x,y,"foo,a,b,bar"
56,92,1234,x,y,"foo,a,b,bar"
56,72,12345478765467,x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar",123454,
56,72,x,y,"foo,a,b,bar",123454,45578492,"bar,foo"

Penjelasan

  • :a: tentukan label yang disebut a.
  • s/(("[0-9,]*",?)*"[0-9,]*),/\1/ : Yang ini perlu dipecah
    • Pertama-tama, menggunakan konstruksi ini: (foo(bar)), \1akan foobardan \2akan bar.
    • "[0-9,]*",?: cocok dengan 0 atau lebih dari 0-9atau ,, diikuti oleh 0 atau 1 ,.
    • ("[0-9,]*",?)* : cocokkan 0 atau lebih dari yang di atas.
    • "[0-9,]*: cocok dengan 0 atau lebih 0-9atau ,yang datang tepat setelah a"
  • ta;: kembali ke label adan jalankan lagi jika substitusi berhasil.
  • s/""/","/g;: pengolahan pasca. Ganti ""dengan ",".
  • s/"([0-9]*)",?/\1,/g : hapus semua tanda kutip di sekitar angka.

Ini mungkin lebih mudah dipahami dengan contoh lain:

$ echo '"1,2,3,4"' | sed -nr ':a;s/(("[0-9,]*",?)*"[0-9,]*),/\1/;p;ta;'
"1,2,34"
"1,234"
"1234"
"1234"

Jadi, sementara Anda dapat menemukan nomor yang tepat setelah penawaran dan diikuti oleh koma dan nomor lain, gabungkan kedua angka tersebut bersama-sama dan ulangi prosesnya hingga tidak mungkin lagi.

Pada titik ini saya percaya akan berguna untuk menyebutkan kutipan dari info sedyang muncul di bagian yang menjelaskan fungsi-fungsi lanjutan seperti label yang digunakan di atas (terima kasih telah menemukan jika @Braiam):

Dalam kebanyakan kasus, penggunaan perintah ini menunjukkan bahwa Anda mungkin lebih baik pemrograman dalam sesuatu seperti `awk 'atau Perl.

terdon
sumber
10

Jika perl OK, berikut ini cara yang singkat (dan mungkin cepat, jika tidak selalu sederhana :)):

perl -pe 's:"(\d[\d,]+)":$1=~y/,//dr:eg' file

The ebendera ke s:::operator (yang hanya cara lain untuk menulis s///) menyebabkan pengganti yang akan diperlakukan sebagai ekspresi yang dievaluasi setiap kali. Ekspresi yang mengambil $1tangkapan dari regex (yang sudah hilang tanda kutip) dan menerjemahkan ( y///, yang juga dapat ditulis sebagai tr///) dengan menghapus ( /d) semua koma. The rbendera untuk yini diperlukan dalam rangka untuk mendapatkan nilai menjadi string diterjemahkan, bukan hitungan terjemahan.

Bagi mereka yang entah bagaimana merasa dinodai oleh perl, di sini adalah setara python. Python sebenarnya bukan alat shell satu-liner, tetapi kadang-kadang dapat dibujuk untuk bekerja sama. Berikut ini dapat ditulis sebagai satu baris (tidak seperti forloop, yang tidak bisa), tetapi pengguliran horizontal membuatnya (bahkan lebih) tidak dapat dibaca:

python -c '
import re;
import sys;
r=re.compile("\"(\d+(,\d+)*)\"");
all(not sys.stdout.write(r.sub(lambda m:m.group(1).replace(",",""),l))
    for l in sys.stdin)
' < file
rici
sumber
@rici: Bagus! Dan gunakan y///alih-alih tr///selamatkan kami satu karakter lagi.
cuonglm
6

Untuk data CSV, saya akan menggunakan bahasa dengan parser CSV nyata. Misalnya dengan Ruby:

ruby -rcsv -pe '
  row = CSV::parse_line($_).map {|e| e.delete!(",") if e =~ /^[\d,]+$/; e} 
  $_  = CSV::generate_line(row)
' <<END
56,72,"12,34,54",x,y,"foo,a,b,bar"
56,92,"12,34",x,y,"foo,a,b,bar"
56,72,"12,34,54,78,76,54,67",x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar","12,34,54"
56,72,x,y,"foo,a,b,bar","12,34,54","45,57,84,92","bar,foo"
END
56,72,123454,x,y,"foo,a,b,bar"
56,92,1234,x,y,"foo,a,b,bar"
56,72,12345478765467,x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar",123454
56,72,x,y,"foo,a,b,bar",123454,45578492,"bar,foo"
glenn jackman
sumber
0

Blokir

Hai Di sini adalah kode Python untuk Mengganti koma dengan tanda kutip ganda, koma diganti dengan karakter pipa (|)

Kode Python ini untuk menggantikan koma yang dilampirkan dalam tanda kutip ganda

misal: x, y, z, 1,2, "r, e, t, y", h, 8,5,6

jika ganti dengan Pipa x, y, z, 1,2, "r | e | t | y", h, 8,5,6

jika ganti dengan nol x, y, z, 1,2, "rety", h, 8,5,6

writingFile = open('FileToWrite', 'w')
with open('FileToRead') as f:

    while True:

        c = f.read(1)
        if not c:
            print ("End of file")
            break
        print ("Read a character:", c)


        if c=='"':
            writingFile.write(c) 
            c = f.read(1)
            while c != '"':
                if c== ',':
                    c= '|'
                writingFile.write(c)
                c = f.read(1)


        writingFile.write(c)


writingFile.close()
Vijay Kumar Akarapu
sumber
sedikit penjelasan yang dibutuhkan.
Mongrel
Kode python ini digunakan untuk menggantikan hal-hal dalam tanda kutip ganda
Vijay Kumar Akarapu