কেবলমাত্র কমা বিস্মৃত ফাইলে কোটের মধ্যে কমা সরান


23

আমার কাছে একটি ইনপুট ফাইল কমা দিয়ে সীমাবদ্ধ হয়েছে ( ,)। ডাবল উদ্ধৃতিতে এমন কিছু ক্ষেত্র রয়েছে যাগুলিতে একটি কমা রয়েছে। এখানে নমুনা সারি

123,"ABC, DEV 23",345,534.202,NAME

আমার ডাবল উদ্ধৃতি এবং ডাবল উদ্ধৃতিগুলির ভিতরে থাকা কমাটির সমস্ত ঘটনাকে সরিয়ে ফেলতে হবে। সুতরাং উপরের লাইনটি নীচে প্রদর্শিত হিসাবে পার্স করা উচিত

123,ABC DEV 23,345,534.202,NAME

আমি নিম্নলিখিতটি ব্যবহার করে চেষ্টা করেছি sedতবে প্রত্যাশিত ফলাফল দিচ্ছি না।

sed -e 's/\(".*\),\(".*\)/\1 \2/g'

সঙ্গে কোন দ্রুত ঠাট sed, awkবা অন্য কোন UNIX ইউটিলিটি প্লিজ?


আপনি কী করতে চাইছেন তা আমি নিশ্চিত নই, তবে সিএসভি পার্স করার জন্য ইউএসটিটি "সিএসভিটিওল" অনেক ভাল সিড বা অ্যাজকের মতো জেনেরিক সরঞ্জামগুলির চেয়ে ভাল। এটি প্রায় প্রতিটি ডিস্ট্রো লিনাক্সের মধ্যে।
11:41

উত্তর:


32

উক্তিগুলি যদি ভারসাম্যপূর্ণ হয় তবে আপনি অন্য প্রতিটি উক্তিটির মধ্যে কমাগুলি সরাতে চাইবেন, এটি এর awkমত প্রকাশ করা যেতে পারে :

awk -F'"' -v OFS='' '{ for (i=2; i<=NF; i+=2) gsub(",", "", $i) } 1' infile

আউটপুট:

123,ABC DEV 23,345,534.202,NAME

ব্যাখ্যা

-F"তোলে ডাবল উদ্ধৃতি অ্যাট চিহ্ন লাইন, প্রত্যেক অন্যান্য ক্ষেত্র আন্ত উদ্ধৃতি পাঠ্য বার্তা পাঠাতে পারবেন যার মানে আলাদা awk। ফর-লুপ রান gsub, বিশ্বব্যাপী বিকল্পের জন্য সংক্ষিপ্ত, প্রতিটি অন্যান্য ক্ষেত্রে, কমা ( ",") কিছুই প্রতিস্থাপন না করে ( "") দিয়ে। 1শেষে ডিফল্ট কোড-ব্লক ডাকে: { print $0 }


1
দয়া করে আপনি কী ব্যাখ্যা করতে পারেন gsubএবং সংক্ষেপে ব্যাখ্যা করতে পারেন , এই এক লাইনার কীভাবে কাজ করে ?? অনুগ্রহ.
mtk

ধন্যবাদ! এই স্ক্রিপ্টগুলি সত্যই ভাল কাজ করে, তবে আপনি কি স্ক্রিপ্টের শেষে নিঃসঙ্গ 1 টি ব্যাখ্যা করতে পারেন? -} 1 '-
কোকোএভ

@ কোকোয়াএভ: এটি কার্যকর করে { print $0 }। আমি ব্যাখ্যা হিসাবে এটি যোগ।
থোর

2
এই পদ্ধতির একটি সমস্যা রয়েছে: কখনও কখনও সিএসভিতে সারি থাকে যা কয়েকটি লাইন বিস্তৃত হয়, যেমন: prefix,"something,otherthing[newline]something , else[newline]3rdline,and,things",suffix (যেমন: বেশ কয়েকটি লাইন এবং নেস্টেড "," বহু-লাইনের ডাবল-কোটিংয়ের মধ্যে যে কোনও জায়গায়: পুরো "...."অংশটি আবার যোগ করা ,উচিত এবং ভিতরে থাকা উচিত) প্রতিস্থাপন / অপসারণ ...): আপনার স্ক্রিপ্টটি এক্ষেত্রে জোড়া ডাবল উক্তিগুলি দেখতে পাবে না এবং এটি সমাধান করা সত্যিই সহজ নয় (একটি "উন্মুক্ত" লাইনে থাকা "পুনরায় যোগদানের প্রয়োজন" (যেমন, বিজোড়-সংখ্যাযুক্ত) ডাবল উক্তি ... + স্ট্রিংয়ের \" ভিতরে যদি কোনও পালাতে পাওয়া যায় তবে অতিরিক্ত যত্ন নিন )
অলিভিয়ার ডুলাক

1
আমি এই সমাধানটি পছন্দ করেছিলাম তবে আমি প্রায়শই কমা রাখতে পছন্দ করি তবে তবুও তারা ডিলিট করতে চাই twe পরিবর্তে, আমি সিএসভিকে একটি পিএসভি ফাইলে রূপান্তর করে, উদ্ধৃতিগুলির বাইরে পাইপগুলিতে কমাগুলি সরিয়েছিলাম:awk -F'"' -v OFS='"' '{ for (I=1; i<=NF; i+=2) gsub(",", "|", $i) } 1' infile
ড্যান্টন

7

একটি লুপ দিয়ে কেবল একবার সময় ব্যবহার করে একটি ভাল সাড়া পাওয়া যায় :

echo '123,"ABC, DEV 23",345,534,"some more, comma-separated, words",202,NAME'|
  sed ':a;s/^\(\([^"]*,\?\|"[^",]*",\?\)*"[^",]*\),/\1 /;ta'
123,"ABC  DEV 23",345,534,"some more  comma-separated  words",202,NAME

ব্যাখ্যা:

  • :a; ফ্রটার শাখার জন্য একটি লেবেল
  • s/^\(\([^"]*,\?\|"[^",]*",\?\)*"[^",]*\),/\1 / 3 বদ্ধ অংশ থাকতে পারে
    • প্রথম ২ য়: [^"]*,\?\|"[^",]*",\?কোনও ডাবল উক্তি সমেত একটি স্ট্রিংয়ের সাথে ম্যাচ করুন, সম্ভবত কোমা বা একটি স্ট্রিং দুটি ডাবল উদ্ধৃতি দ্বারা আবদ্ধ, কোমা ছাড়াই এবং সম্ভবত কোমা দ্বারা অনুসরণ করা হবে।
    • প্রথম বারের চেয়ে পুনরায়- অংশ পূর্বে বর্ণিত পার্ট 2 অনেক পুনরাবৃত্তি, 1 ডাবল উদ্ধৃতি এবং কিছু caracteres দ্বারা অনুসরণ, কিন্তু কোন ডাবল উদ্ধৃতি, কিংবা comas যেমন দ্বারা গঠিত হয়।
    • কোমা দ্বারা অনুসরণ করা হিসাবে প্রথম আরই অংশ।
    • না, বাকি রেখার ছোঁয়া লাগার দরকার নেই
  • ta:aপূর্ববর্তী s/কমান্ডটি কিছু পরিবর্তন করেছে কিনা লুপ হবে ।

নেস্টেড কোটগুলি নিয়েও কাজ করে। অান্তরিক ধন্যবাদ!
tricasse

5

একটি সাধারণ সমাধান যা সুষম উদ্ধৃতিগুলির মধ্যে বেশ কয়েকটি কমা পরিচালনা করতে পারে তার জন্য নেস্টেড প্রতিস্থাপনের প্রয়োজন। আমি পার্লে একটি সমাধান প্রয়োগ করি, যা প্রদত্ত ইনপুটটির প্রতিটি লাইনকে প্রক্রিয়াজাত করে এবং প্রতিটি অন্য জোড়ের উদ্ধৃতিতে কেবল কমা পরিবর্তিত করে:

perl -pe 's/ "  (.+?  [^\\])  "               # find all non escaped 
                                              # quoting pairs
                                              # in a non-greedy way

           / ($ret = $1) =~ (s#,##g);         # remove all commas within quotes
             $ret                             # substitute the substitution :)
           /gex'

বা সংক্ষেপে

perl -pe 's/"(.+?[^\\])"/($ret = $1) =~ (s#,##g); $ret/ge'

আপনি যে পাঠ্যটি কমান্ডটি প্রসেস করতে চান তা পাইপ করতে পারেন বা শেষ কমান্ড লাইন আর্গুমেন্ট হিসাবে প্রক্রিয়াকরণের জন্য পাঠ্য ফাইলটিকে নির্দিষ্ট করতে পারেন।


1
[^\\]কোট ভিতরে শেষ অক্ষর মিলে এবং এটি (অ \ চরিত্র) অপসারণ, অর্থাত্ অবাঞ্ছিত প্রভাব আছে যাচ্ছে, আপনি যে চরিত্র গ্রাস করা উচিত নয়। (?<!\\)পরিবর্তে চেষ্টা করুন।
tojrobinson

আপনার আপত্তি জন্য ধন্যবাদ, আমি এটি সংশোধন করেছি। তবুও আমি মনে করি আমাদের এখানে দৃser়তার পিছনে তাকানোর দরকার নেই, বা আমরা কি করব !?
ব্যবহারকারী 1146332

1
আপনার ক্যাপচার গ্রুপে নন Inc অন্তর্ভুক্ত করা সমমানের ফলাফল দেয়। +1
tojrobinson

1
+1 টি। সেডের সাথে কয়েকটি জিনিস চেষ্টা করার পরে আমি সেডের ডক্স পরীক্ষা করে নিশ্চিত করেছিলাম যে এটি কোনও লাইনের সাথে মিলে যাওয়া অংশে প্রতিস্থাপন প্রয়োগ করতে পারে না ... তাই ছেড়ে দিয়ে পার্ল চেষ্টা করেছিলাম। অনুরূপ একটি পদ্ধতির কিন্তু এই সংস্করণ ব্যবহার করে সঙ্গে শেষ পর্যন্ত [^"]*ম্যাচ অ লোভী করতে (অর্থাত এক থেকে সবকিছু মিলে যায় "থেকে পরবর্তী " ): perl -pe 's/"([^"]+)"/($match = $1) =~ (s:,::g);$match;/ge;'। এটা তোলে বিদঘুটে ধারণা স্বীকার নয় যে উদ্ধৃতি একটি ব্যাকস্ল্যাশ :-) সঙ্গে পলান করা যেতে পারে
CA গুলির

আপনার মন্তব্যের জন্য ধন্যবাদ. আকর্ষণীয় হবে যদি হয় [^"]*পদ্ধতির বা স্পষ্টতই লোভী দৃষ্টিভঙ্গি কম সিপিইউ সময় নেয়।
ব্যবহারকারী 1146332

3

আমি একটি উপযুক্ত সিএসভি পার্সার সহ একটি ভাষা ব্যবহার করব। উদাহরণ স্বরূপ:

ruby -r csv -ne '
  CSV.parse($_) do |row|
    newrow = CSV::Row.new [], []
    row.each {|field| newrow << field.delete(",")}
    puts newrow.to_csv
  end
' < input_file

আমি প্রথমদিকে এই সমাধানটি পছন্দ করলেও বড় ফাইলগুলির জন্য এটি অবিশ্বাস্য ধীর হয়ে উঠল ...
কেআইসি

3

আপনার দ্বিতীয় উদ্ধৃতিটি ভুল জায়গায় প্রতিস্থাপন করা হয়েছে:

sed -e 's/\(".*\),\(.*"\)/\1 \2/g'

এছাড়াও, নিয়মিত এক্সপ্রেশন ব্যবহার করে পাঠ্যের দীর্ঘতম অংশের সাথে মেলে meaning

একটি উপায় যা সেডে একাধিক উদ্ধৃত ক্ষেত্রগুলি পরিচালনা করে

sed -e 's/\(\"[^",]\+\),\([^",]*\)/\1 \2/g' -e 's/\"//g'

এটি সমাধানেরও এটি একটি উপায়, তবে ইনপুট সহ যে উদ্ধৃত ক্ষেত্রের প্রতি একাধিক কমা থাকতে পারে সেডের প্রথম অভিব্যক্তিটি একক ক্ষেত্রে সর্বাধিক কমা কন্টেন্ট হিসাবে বহুবার পুনরাবৃত্তি করতে হবে, বা এটি না হওয়া পর্যন্ত আউটপুট মোটেও পরিবর্তন করে না।

একাধিক এক্সপ্রেশন দিয়ে সেড চালানো বেশ কয়েকটি সেড প্রক্রিয়াগুলির চেয়ে বেশি দক্ষ হওয়া উচিত এবং খোলা পাইপগুলি সহ "ট্র" সমস্ত চলমান।

যাইহোক, যদি ইনপুটটি সঠিকভাবে ফর্ম্যাট না করা হয় তবে এর অনাকাঙ্ক্ষিত পরিণতি হতে পারে। অর্থাত নেস্টেড কোট, নিরবিচ্ছিন্ন উদ্ধৃতি।

চলমান উদাহরণ ব্যবহার করে:

echo '123,"ABC, DEV 23",345,534,"some more, comma-separated, words",202,NAME' \
| sed -e 's/\(\"[^",]\+\),\([^",]*\)/\1 \2/g' \
-e 's/\(\"[^",]\+\),\([^",]*\)/\1 \2/g' -e 's/\"//g'

আউটপুট:

123,ABC  DEV 23,345,534,some more  comma-separated  words,202,NAME

আপনি এটি শর্তসাপেক্ষ শাখা দ্বারা আরও সাধারণ করতে এবং ERE এর সাথে আরও পাঠযোগ্য, যেমন GNU সেড সহ: করতে পারেন sed -r ':r; s/("[^",]+),([^",]*)/\1 \2/g; tr; s/"//g'
থর

2

পার্ল - আপনি এটি Text::CSVবিশ্লেষণ করতে এবং তুচ্ছভাবে এটি করতে পারেন:

#!/usr/bin/env perl
use strict;
use warnings;

use Text::CSV; 

my $csv = Text::CSV -> new();

while ( my $row = $csv -> getline ( \*STDIN ) ) {
    #remove commas in each field in the row
    $_ =~ s/,//g for @$row;
    #print it - use print and join, rather than csv output because quotes. 
    print join ( ",", @$row ),"\n";
}

আপনার সাথে মুদ্রণ করতে পারেন Text::CSVকিন্তু এটা কোট সংরক্ষণ যদি আপনি না থাকে। (যদিও, আমি আপনাকে পরামর্শ দিচ্ছি থাকব - বদলে stripping আপনার আউটপুট কোট, আপনি শুধু ব্যবহার পার্স পারে Text::CSVপ্রথম স্থানে)।


0

আমি স্ট্রিংয়ের প্রতিটি চরিত্রের লুপ করতে একটি ফাংশন তৈরি করেছি।
অক্ষরটি যদি একটি উদ্ধৃতি হয় তবে চেকটি (b_in_qt) সত্য হিসাবে চিহ্নিত হয়েছে।
যখন b_in_qt সত্য, সমস্ত কমা একটি স্থান দিয়ে প্রতিস্থাপিত হয়।
পরের কমাটি পাওয়া গেলে b_in_qt টি মিথ্যাতে সেট করা থাকে।

FUNCTION f_replace_c (str_in  VARCHAR2) RETURN VARCHAR2 IS
str_out     varchar2(1000)  := null;
str_chr     varchar2(1)     := null;
b_in_qt     boolean         := false;

BEGIN
    FOR x IN 1..length(str_in) LOOP
      str_chr := substr(str_in,x,1);
      IF str_chr = '"' THEN
        if b_in_qt then
            b_in_qt := false;
        else
            b_in_qt := true;
        end if;
      END IF;
      IF b_in_qt THEN
        if str_chr = ',' then
            str_chr := ' ';
        end if;
      END IF;
    str_out := str_out || str_chr;
    END LOOP;
RETURN str_out;
END;

str_in := f_replace_c ("blue","cat,dog,horse","",yellow,"green")

RESULTS
  "blue","cat dog horse","",yellow,"green"
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.