অ্যাজক ব্যবহার করে কলামগুলি পুনরায় সাজানো হচ্ছে


13

আমি আমার সিএসভি ফাইলের 7 তম কলামটি ব্যবহার করে শেষের দিকে নিয়ে যাওয়ার চেষ্টা করছি

awk -F '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}',OFS= "$file"

যেখানে $ ফাইলটি একটি ডিরেক্টরিতে একটি .csv ফাইল। তবে আউটপুট হয়

awk:                          ^ syntax error

কেউ কীভাবে এই ত্রুটিটি ঠিক করতে জানেন?


7
বিশ্রী ত্রুটিগুলি দেখানোর সময়, আপনাকে পুরো জিনিসটি দেখাতে হবে। ^কমান্ড যেখানে সমস্যা দেখা দিয়েছে নির্দিষ্ট অংশ নির্দেশ করে।
টেরডন

উত্তর:


11

-Fবিকল্প একটি আর্গুমেন্ট দরকার: -F,উদাহরণস্বরূপ।

শেষে awkস্ক্রিপ্ট একটি দিয়ে পৃথক করা আবশ্যক পরামিতি বাকি সঙ্গে (স্থান গৃহস্থালির কাজ)।

যদি ক্ষেত্রের বিভাজক হয় ,এবং আপনি এটি রাখতে চান এবং যদি কলামের সংখ্যা স্থির হয় এবং 11 এর চেয়ে কম বা এর সমান হয় তবে এটি চেষ্টা করে দেখুন:

awk -F, '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}' OFS=, "$file"

8
@ অ্যানুরিব খুব কম প্রোগ্রামেই এটির অনুমতি দেয়। মানক উপায় command file > newfile && mv newfile file। যে বলেন, গনুহ এর নতুন সংস্করণ awkএই সমর্থন করার জন্য: gawk -i inplace '{blah blah}' file
টেরডন

1
বিকল্পভাবে, পরিবর্তে mv newfile fileআপনি ব্যবহার করতে পারেন cat newfile > file ; rm -f newfile- এটি এর ইনোড এবং অনুমতি সংরক্ষণ করে file
ক্যাস

এবং সাধারণত mktempস্ক্রিপ্টগুলিতে অস্থায়ী ফাইলের নামগুলি হার্ড-কোডিংয়ের পরিবর্তে ব্যবহার করা ভাল । যেমনtf=$(mktemp) ; command file > "$tf" ; cat "$tf" > file ; rm -f "$tf"
সি এ এস

8

সংক্ষিপ্ত সমাধান হবে

awk -F',+' -v OFS=, '{$(NF+1)=$7; $7=""; $0=$0; $1=$1}1' file

আমি নিশ্চিত না যে ,+সমস্ত awkসংস্করণে কাজ করবে কিনা , তবে কমপক্ষে জিএনইউ -cঅ্যাড-এ কাজ করে omp

ব্যাখ্যা:

  • $(NF+1)=$7: প্রথমে আমরা লাইনের শেষে 7 তম ক্ষেত্র যুক্ত করব ( $12=$7এই ক্ষেত্রে হতে পারে )
  • $7="": পরবর্তী ধাপে 7th ম ক্ষেত্রটি মুছে ফেলা হয়েছে (তবে আশেপাশের সীমানা বিহীন)
  • ডিলিমিটারগুলি অপসারণ করতে আমাদের $0=$0একাধিক কমাতে ক্ষেত্র বিভাজক হিসাবে আচরণ করার মাধ্যমে পুরো রেকর্ডটি পুনরায় সেট করতে হবে ( এটি এর মাধ্যমে করা হয় -F',+', এখানে +এক বা একাধিক বার বোঝানো হয়েছে), এবং $1=$1পূর্ববর্তী সেট আউটপুট ক্ষেত্রটি ব্যবহার করে লাইনটি পুনর্নির্মাণের জন্য বর্তমান রেকর্ডটিকে পুনর্বিন্যাস করা দরকার বিভাজক (একটি বিকল্প দ্বারা সেট -v OFS=,)
  • সব বদলে যাওয়ার পরে আমরা ফলাফলটি মুদ্রণের জন্য প্রস্তুত 1

উদাহরণ ইনপুট:

1,2,3,4,5,6,7,8,9,10,11

আউটপুট

1,2,3,4,5,6,8,9,10,11,7

যদি অন্য কলামগুলি ফাঁকা থাকে? তবে, হ্যাঁ, এফএস POSIX এ নিয়মিত প্রকাশ (যদি এটি একাধিক অক্ষর হয়), তাই ,+কাজ করা উচিত।
র্যান্ডম 832

(1) আমি বুঝতে পারি যে ইনপুট ডেটার সপ্তম কলামটি "অদৃশ্য" হয়ে যাওয়া, এবং কেবল এটি বাতিল করার উদ্দেশ্যে সেট করা নয়, এই সমস্যার একটি জটিল বিষয়। তবে, র্যান্ডম 832 যেমন বলেছেন, আপনার সমাধান ক্লোবারগুলি খালি কলামগুলি (উদাহরণস্বরূপ, all,ball,call,,,fallall,ball,call,fall)। (2)  $(NF+1)=$7একটি চতুর পদ্ধতির। আইএমএইচও, আরও $0 = $0 OFS $7পরিষ্কার, কেবলমাত্র কয়েকটি অক্ষর দীর্ঘ, এবং মনে হয় এটি একই কাজ করবে। আপনি কি এমন পরিস্থিতি সম্পর্কে ভাবতে পারেন যা $0 = $0 OFS $7আপনার কোডের মতো করে না?
জি-ম্যান

@ র্যান্ডম 832 @ জি-ম্যান হ্যাঁ, কিছু প্রান্তের ক্ষেত্রে যেমন ফাঁকা ক্ষেত্র, ফাঁকা লাইন বা এনএফ <7 আলাদাভাবে চিকিত্সা করা উচিত বা একটি কোড পুনরায় সাজানো উচিত। এটি কেবলমাত্র একটি ধারণা, সমস্ত সাধারণ ক্ষেত্রে "সম্পূর্ণ সমাধান" নয়, এটি পরিষ্কার হওয়া উচিত। $0=$0 OFS $7সম্ভবত এটির জন্য অভিন্ন $(NF+1)=$7, তবে কেবলমাত্র কোডটি অপরিবর্তিত রয়েছে, সাধারণভাবে নয়।
জিম্মিজ

5

আপনি যদি মুদ্রণ করছেন OFS=, তাই ক্ষেত্রগুলির মধ্যে কোনও বিভাজক না থাকলে আপনি কেবল $7ভেরিয়েবলের মান সংরক্ষণ করতে পারেন , $7খালি সেট করে লাইনটি এবং ভেরিয়েবলটি সরাসরি মুদ্রণ করতে পারেন। আপনাকে সমস্ত ক্ষেত্র নির্দিষ্ট করার দরকার নেই:

$ cat file
1,2,3,4,5,6,7,8
$ awk -F, -vOFS= '{k=$7; $7=""; print $0,k}' file 
12345687

3

আপনার সম্ভবত সম্ভবত:

awk -F, -v OFS='' '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}' "$file"

আপনি জানেন যে awkএকক উদ্ধৃতি কখনও দেখেন না OFS='', তাই না? আপনি পাশাপাশি টাইপ করতে পারেন OFS=; এটা ঠিক একই।
ওয়াইল্ডকার্ড

1
হ্যাঁ, আমি বুঝতে পারি তবে, আমি ঝুঁকির কাজগুলি অপছন্দ করি।
মাইকেল Vehrs


3

আপনি বিশদে নির্দিষ্টভাবে বলেননি যে আপনি বিশ্রী ব্যবহার করতে চেয়েছিলেন, এবং আপনি বলেছিলেন যে আপনি সরবরাহ করেছেন এমন জায়গায় স্থান সম্পাদনা ব্যবহার করতে চেয়েছিলেন sed -i, সুতরাং এখানে একটি sed -iবৈকল্পিক is awkকলামগুলির সাথে কাজ করার জন্য সাধারণত ভাল তবে এটি এমন একটি ক্ষেত্রে যেখানে আমি পছন্দ করি sedকারণ এটি স্বাভাবিকভাবেই সংখ্যক কলামগুলিকে পরিচালনা করে।

MOVECOL=7
N=$((MOVECOL-1))
sed -r -e "s/^(([^,]*,){$N})([^,]*),(.*)/\1\4,\3/" -i test.csv

ব্যাখ্যা:

  • -r প্রসারিত রিজেক্সপস নির্বাচন করে যাতে আমরা প্রচুর ব্যাকস্ল্যাশগুলি এড়ানো পারি
  • প্রথম গোষ্ঠীটি হ'ল কমা-সমাপ্ত স্ট্রিংগুলির etition N পুনরাবৃত্তি, অন্য কথায় চূড়ান্ত কমা সহ আমরা কলামগুলি সরিয়ে নিতে চাই তার আগে কলামগুলি হয়
  • দ্বিতীয় গ্রুপটি হ'ল $ N-th পুনরাবৃত্তি, আমরা এটির কথা ভুলে যাই
  • তৃতীয় গোষ্ঠী হ'ল চূড়ান্ত কমা ব্যতীত আমরা কলামটি স্থানান্তর করতে চাই
  • চতুর্থ গোষ্ঠীটি আমরা যে কলামে যেতে চাইছি তার পরে সমস্ত কলাম তৈরি করে এর আগে কোনও কমা নেই ma
  • আমরা প্রথম গোষ্ঠী, শেষ গ্রুপ এবং কলামটি বের করেছি যার সাথে কমাটি প্রয়োজনীয় হিসাবে সন্নিবেশ করিয়েছি replace

অবশ্যই এটি সেই ফাইলগুলির সাথে কাজ করবে না যা উদ্ধৃতিগুলিতে কমাগুলি লুকিয়ে রাখে (বা আরও খারাপ, সেগুলি থেকে পালাতে পারে), তবে কিছুটা গুরুতর অ্যাক্রোব্যাটিক্স ছাড়াই অজক এটি পরিচালনা করতে পারে না। আপনি যে সমস্যা আছে আপনার সাথে ভাল হতে চাই perlমডিউল Text:CSVবা pythonমডিউল csv


2

বেশ কয়েকটি awkভেরিয়েন্ট (ধরে নিচ্ছেন আপনার ফাইলটি ভেরিয়েবলের মধ্যে রয়েছে $file)

  • এখানে আপনি সমস্ত কলুমনের জন্য চক্র রাখতে পারেন, ফিল্ড বিভাজক (ওএফএস) দিয়ে মুদ্রণ করতে পারেন এবং লাইনটির শেষে রেকর্ড টার্মিনেটর (ওআরএস) মুদ্রণ করতে পারেন।

    awk  -F',' -v OFS=,                                \
    '{for(i=1;i<=NF;i++) if (i!=7) printf "%s",$i OFS; \
    printf "%s",$7;printf ORS}' "$file"
    
  • এখানে একটি রেইজেক্স এবং gensub()ফাংশন ব্যবহার করে

    gawk -F',+' -v OFS=, '{$0=gensub(/\s*\S+/,"",7) OFS $7}1' "$file"

    হত্যা 7 ক্ষেত্র এবং লাইন শেষে এটা মুদ্রণ।

    • $0 পুরো রেকর্ড
    • $nএটি এন রেকর্ড
    • NF বর্তমান লাইনের ক্ষেত্র সংখ্যা is
    • OFS আউটপুট বিভাজক ফাইল
    • ORS আউটপুট রেকর্ড টার্মিনেটর
    • 1trueডিফল্ট ( $0) মুছে ফেলা এবং মুদ্রণ করতে বলার কৌশল ।

আপডেট করুন ...

আমি প্রায় ভুলে গেছি, 7 তম অনুসরণ করে সমস্ত কলামগুলি স্থানান্তর করা সম্ভব ।

awk  -F',' -v OFS=, '{tmp=$7; for(i=7;i<=NF;i++) $i=$(i+1); $NF=tmp}1 ' "$file"

(1) যুক্তিযুক্তভাবে, এর OFS $7চেয়ে আরও শক্তিশালী হবে "," $7। (২) আমি বিশ্বাস করি যে ", " $7এটি ভুল, ইনসোফার হিসাবে প্রশ্নটি ইঙ্গিত দেয় যে ওপি কমাগুলির পরে স্পেস চায় না। (এবং, যদি ইনপুট ডেটার কমাগুলির পরে ফাঁকা স্থান থাকে, তবে $7ইতিমধ্যে একটি স্পেস দিয়ে শুরু হবে, এবং আপনি একটি অতিরিক্ত যোগ করতে চাইবেন))
জি-ম্যান

@ জি-ম্যানটি মূলত কিছু ধারণা, কিছু বৈকল্পিকের প্রস্তাব দেওয়া হয়েছিল। ধন্যবাদ, স্পটটির জন্য, আমি OFS $7কেবলমাত্র আরও
দৃ ,়
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.