ডিলিমিটার সহ তালিকাটিকে একক লাইনে পরিণত করুন


17

আমাকে এই ফর্ম্যাটে আইপি ঠিকানাগুলির একটি তালিকা (বোঝা) নিতে হবে:

 134.27.128.0
 111.245.48.0
 109.21.244.0

এবং এগুলির মধ্যে একটি পাইপের সাথে এই ফর্ম্যাটটিতে পরিণত করুন (আইপিগুলি তৈরি করা হয়েছে)

134.27.128.0 | 111.245.48.0 | 109.21.244.0 | 103.22.200.0/22

আমি মনে করি এটি একটি ফাইন্ড এন্ড রিপ্লেস কমান্ডের মত sedতবে আমি এটি কাজ করতে পারি না।


3
আপনি কেবল trপাইপগুলিতে নতুন লাইনের উত্তর দিতে চান |? পছন্দ <ipfile tr \\n \| >outfile?
মাইক্রজারভ

চারপাশের স্থান কি |প্রয়োজনীয়?
কিউংলম

2
@ ইউসলেসলিনক্সম্যান - না আপনার ইনপুট পুনর্নির্দেশের প্রয়োজন <। তাই <mydoc tr \\n \| >mydoc2। কিন্তু এটি আপনাকে স্পেসগুলি পাবে না। তাদের জন্য, সম্ভবত দ্রুততম সমাধানpaste -d' | ' mydoc /dev/null /dev/null >mydoc2
mikeserv

1
@ মিমকিজার: আমার মনে হয় না এটি কার্যকর হবে। pasteপ্রতিটি ফাইল থেকে অনুরূপ লাইন লিখুন। ছাড়া -s, আপনি ফিরে লাইনের নম্বর পেতে হবে ফাইলে আছে।
কিউংলম

2
@ val0x00ff: আমি আপনাকে unix.stackexchange.com/q/169716/38906
কিউংএলএম

উত্তর:


16

বিখ্যাত শেড ওয়ান-লাইনার বর্ণিত উপর ভিত্তি করে সেড ব্যবহার করুন , প্রথম অংশ : 39 : যদি ব্যাকস্ল্যাশ "\" দিয়ে শেষ হয় তবে পরবর্তীটিতে একটি লাইন যুক্ত করুন (এখানে ব্যতীত আমরা ব্যাকস্ল্যাশ সম্পর্কে অংশটিকে উপেক্ষা করে \nনতুন লাইনের সাথে প্রতিস্থাপন করব ) প্রয়োজনীয় |বিভাজক):

sed -e :a -e '$!N; s/\n/ | /; ta' mydoc > mydoc2

মধ্যে উত্পাদন করা উচিত mydoc2

134.27.128.0 |  111.245.48.0 |  109.21.244.0

@ ডন_ক্রিস্তি দুঃখিত যে এটি একধরণের ছিল - সংশোধন হয়েছে, ধন্যবাদ
স্টিল্ড্রাইভার

দুর্ভাগ্যক্রমে এটি বাস্তবে বাস্তবে কাজ করে না। কমপক্ষে, সীমাহীন স্ট্রিমগুলির জন্য নয়। আপনি যখন এটি করেন তখন আপনার পুরো ইনপুটকে একবারে একটি লাইন গিলে ফেলতে হয় এবং আপনি এটি হজম না করা পর্যন্ত এটির একটি একক বাইটও আউটপুটটিতে লিখতে পারবেন না - এগুলি সমস্ত একক লাইনে রূপান্তরিত হয়। এটি অযৌক্তিক এবং সেগফল্টের প্রবণ।
মাইকসার্ভ

এক মিলিয়ন আইপি <16 এম, আপনার এখানে সীমাবদ্ধতা বাড়াতে খুব বড় তালিকা দরকার। ইওফ সনাক্তকরণের জন্য অনুসন্ধান ব্যবহার করা আরও সমস্যাযুক্ত, যেমন এটি ইনপুট ফাইলের আকারে ও (N ^ 2) চালাবে। sed 'H;1h;$!d;x;s/\n/ | /g'রৈখিক
jthill

@ জেথিল - পসিক্স কেবলমাত্র sed8 কে এর প্যাটার্ন স্পেসের গ্যারান্টি দেয় ; এটি পুরো 16M এর চেয়ে অনেক কম।
মাইকসার্ভ

9

আমি দেখতে অদ্ভুত ছিল কিভাবে এর মধ্যে কিছু (কিছু বিকল্প + +) একটি বরং বড় ফাইলের সাথে গতি-অনুযায়ী ( 163MiBএক IPপ্রতি লাইনে ~ 13 মিলিয়ন লাইন):

wc -l < iplist
13144256

ফলাফল ( sync; echo 3 > /proc/sys/vm/drop_cachesপ্রতিটি কমান্ডের পরে; আমি পরীক্ষাগুলি পুনরুদ্ধার করে - কয়েক ঘন্টা পরে রিফ্রাক্ট করেছিলাম তবে পার্থক্যগুলি নগণ্য ছিল; এছাড়াও লক্ষ করুন যে আমি ব্যবহার করছি gnu sed):

স্টিল্ড্রাইভার :
খুব ধীর। দুই মিনিট অপেক্ষা করার পরে বাতিল করা হয়েছে ... সুতরাং এটির কোনও ফলাফল নেই।

কিউংলম :

awk 'FNR!=1{print l}{l=$0};END{ORS="";print l}' ORS=' | ' iplist

real    0m3.672s

perl -pe 's/\n/ | / unless eof' iplist

real    0m12.444s

মাইকজার্ভ :

paste -d\  /dev/null iplist /dev/null | paste -sd\| - 

real    0m0.983s

জেথিল :

sed 'H;1h;$!d;x;s/\n/ | /g' iplist

real    0m4.903s

অবিনাশ রাজ :

time python2.7 -c'
import sys
with open(sys.argv[1]) as f:
    print " | ".join(line.strip() for line in f)' iplist

real    0m3.434s

এবং

val0x00ff :

while read -r ip; do printf '%s | ' "$ip"; done < iplist

real    3m4.321s

যার অর্থ 184.321s। আশ্চর্যজনকভাবে, এটি মাইক্রজার্ভের সমাধানের চেয়ে 200 গুণ ধীর ।



অ্যাজকের সাথে এখানে আরও কয়েকটি উপায় রয়েছে :

awk '$1=$1' RS= OFS=' | ' iplist

real    0m4.543s

awk '{printf "%s%s",sep,$0,sep=" | "} END {print ""}' iplist

real    0m5.511s

Perl:

perl -ple '$\=eof()?"\n":" | "' iplist

real    0m9.646s

xargs:

xargs <iplist printf ' | %s' | cut -c4-

real    0m6.326s

মাথা + পেস্ট + টিআর + বিড়ালের সংমিশ্রণ:

{ head -n -1 | paste -d' |' - /dev/null /dev/null | tr \\n \ ; cat ; } <iplist

real    0m0.991s

আপনার যদি থাকে GNU coreutilsএবং আপনার আইপিগুলির তালিকাটি যদি সত্যিই বিশাল না হয় (আসুন 50000 আইপি পর্যন্ত বলা যাক) আপনি এটি দিয়েও করতে পারেন pr:

pr -$(wc -l infile) -tJS' | ' -W1000000 infile >outfile

কোথায়

-$(wc -l infile)         # no. of columns (= with no. of lines in your file)
-t                       # omit page headers and trailers
-J                       # merge lines
-S' | '                  # separate columns by STRING
-W1000000                # set page width

উদাহরণস্বরূপ 6-লাইনের ফাইলের জন্য:

134.28.128.0
111.245.28.0
109.245.24.0
128.27.88.0
122.245.48.0
103.44.204.0

আদেশ:

pr -$(wc -l <infile) -tJS' | ' -W1000 infile

আউটপুট:

134.28.128.0 | 111.245.28.0 | 109.245.24.0 | 128.27.88.0 | 122.245.48.0 | 103.44.204.0

ডন - আপনি কি লুপটির জন্য @ Val0x00ff দ্বারা প্রশ্নের পরামর্শটিতে যুক্ত করতে পারেন while ... read? আমি কৌতূহল করছি কি 163 কে read()এবং write()কল একটি মানদণ্ডে কী অনুবাদ করে। দুর্দান্ত উত্তর, যাইহোক।
মাইকসার্ভ

1
@ মাইকজার - কোনও সমস্যা নেই, আমি এটি করব ( যদিও এটি সত্যিই ধীর হবে )।
don_crissti

এটি একটি দুর্দান্ত লিঙ্ক। আমি বিশেষত পছন্দ করি যে লেখক সেখানে একটি অনুরূপ 6 বছরের পুরানো বেনমার্কের সাথে একটি লিঙ্কও সরবরাহ করেন। আপনি কি লক্ষ্য করেছেন যে sedসেই সময়ের মধ্যে এর অবস্থানটি উন্নত হয়েছে বলে মনে হচ্ছে (এবং সম্ভবত তার রেজিএক্সএক্স ইঞ্জিনে খুব কম কিছু পরিবর্তন হয়েছিল) তবে grepমনে হয় এর অভিনয় (বিশেষত দীর্ঘ লাইনের জন্য) নাটকীয়ভাবে পিছিয়ে পড়েছে ? আমি অবাক হই যে perlএর ইঞ্জিনে সংযোজনগুলি যদি সেই ফলাফলগুলিতে কোনও প্রভাব ফেলে ... এটি খুব ঝরঝরে dashনয় যা অস্বাভাবিক নয় । bashএখানে সম্ভবত পর্যন্ত ধীর W হবে / সাধারণ IFS=prepended।
মাইকসার্ভ

হুম ... সেই লিঙ্কটি আরও একটি শক্তিশালী সূচক যা আমাকে সত্যিই নীচে টানতে এবং সি শিখতে হবে যাতে আমি শেষ পর্যন্ত lexসঠিকভাবে ব্যবহার শুরু করতে পারি ।
মাইকসার্ভ

8

আপনি awk ব্যবহার করতে পারেন :

awk 'FNR!=1{print l}{l=$0};END{ORS="";print l}' ORS=' | ' file > new_file

ORS=' | 'সেট আউটপুট রেকর্ড বিভাজক থেকে ' | 'সম্পর্কে newline পরিবর্তে।

অথবা সাথে জায়গায় স্থান সম্পাদনা করুন perl :

perl -pe 's/\n/ | / unless eof' file

ধন্যবাদ মানুষ. আমি কেবল শিখলাম কীভাবে pasteকাজ করে। অনেক প্রশংসিত.
মাইকসার্ভ

@ মিমকিজার: আপনাকে স্বাগতম Don_crissti হিসাবে তার মানদণ্ডে দেখানো হয়েছে, pasteসমাধানটি দ্রুততম।
কিউংলম

আউটপুট একটি নতুন লাইন দিয়ে শেষ হয় না। আপনাকে ব্লকের ORS=""ভিতরে এটি প্রতিস্থাপন করতে হবে যাতে এটি করে। ENDORS="\n"
পিএইচকে

4

সুতরাং আমার পুরো বিষয়টি ভুল ছিল - এবং এই প্রশ্নটি আমাকে সম্পর্কে অনেক কিছু শিখিয়েছে paste। কিউওংএলএম সঠিকভাবে নোট করেছে, আপনি যদি ইরিলে pasteফাইল না করেন তবে আপনি -sসর্বদা \nডাব্লু / আপনার সর্বশেষের অনলাইন তালিকাটি লেখা হিসাবে আউটপুটে সংযুক্ত হয়ে আপনার লিখিত তালিকা থেকে শেষ করে দেবেন। আমার বিশ্বাস ছিল ভুল ছিল যে paste -sআচরণটি এটির পূর্বনির্ধারিত মোড - এবং এটি একটি ভুল ধারণা যা স্পষ্টতইbusybox paste প্রয়োগ করতে পেরে খুশি হয়েছিল। নিম্নলিখিত কমান্ডটি বিজ্ঞাপনযুক্ত ডাব্লু / হিসাবে কাজ করে busybox:

paste -d'|  ' - - infile </dev/null >outfile

যদিও এটি অনুমান অনুযায়ী কাজ করে না। একটি সঠিকভাবে প্রয়োগ করা প্রতিটি লেখার ক্রমের জন্য pasteএকটি ট্রিলিং \nইওলাইন যুক্ত করবে । তবুও, এটি সর্বোপরি কোনও বড় বিষয় নয়:

paste -d\  - infile - </dev/null | paste -sd\| - >outfile

@ don_crissti - ডাঙ্গিত। বোকা ট্যাবলেট। আমি অনুমান করি যে সুস্পষ্ট জিনিসটি হ'ল দুটি আটকানো।
মাইকসার্ভ

1
ঠিক আছে, আমার মনে ছিল prতবে স্পষ্টতই এটি বিশাল ইনপুট ফাইলগুলির সাথে বাষ্পের বাইরে চলে যায় তাই আমি আসলে গতিটি পরীক্ষা করতে পারিনি তবে যুক্তিযুক্ত দৈর্ঘ্যের ফাইলগুলির সাথে এটি ঠিক আছে। আপনার সমাধানটি এখন পর্যন্ত দ্রুততম (কোনও আশ্চর্য নয় - pasteসত্যিই দ্রুত), আমার পোস্টটি দেখুন।
don_crissti

4

টিআর এবং সেডযুক্ত এক-লাইনার:

cat file | tr '\n' '|' | sed 's/||$/\n/'
134.27.128.0|111.245.48.0|109.21.244.0

2 টি পেছনের পাইপ মুছবেন কেন? ইনপুটটি ফাঁকা লাইন (দুটি নতুন লাইন) দিয়ে শেষ হলে কেবলমাত্র 2 জন থাকবে।
জিগ্লিনাগা

3

ব্যবহার vim:

vim -n -u NONE -c '1,$-1s/\n/ | /g|wq!' data

ব্যাখ্যা:

-n অদলবদল অক্ষম করুন

-u NONE সমস্ত সূচনা এড়ানোর জন্য ব্যবহৃত হয়।

-c {command} ফাইল পড়ার পরে কমান্ডগুলি কার্যকর করুন।

1,$-1s/\n/ | /g হয় s/\n/ | /g পরিসীমা জন্য (স্থান নল স্থান সঙ্গে সম্পর্কে newline প্রতিস্থাপন) 1,$-1s(শেষ লাইন 1st লাইন - 1)

wq! জোর করে লিখুন এবং ছেড়ে দিন


বিঃদ্রঃ:

আপনার ফাইলটি আসলে কত বড় তার উপর নির্ভর করে এটি একটি খারাপ ধারণা হতে পারে।


1
আমি আপনাকে সকলকে ধন্যবাদ জানাই, কারণ মূলত এই কমান্ডগুলির প্রত্যেকটিই আমার অর্জনের জন্য কাজ করে। আমি জানি এখন কোথায় আসব যদি (কখন) আমি আবার আটকে থাকি। ধন্যবাদ
ব্যবহারহীনলিঙ্কসম্যান

2

অজগর মাধ্যমে।

$ python -c '
import sys
with open(sys.argv[1]) as f:
    print " | ".join(line.strip() for line in f)' file

স্পেস আগে printখুব গুরুত্বপূর্ণ ছিল।


2

এখানে আরেকটি ব্যবহার করা হচ্ছে xxd

xxd -c1 -ps data | sed '$!s/0a/207c20/' | xxd -r -ps

2

সম্পূর্ণতার জন্য, এখানে আরেকটি awkভিত্তিক সমাধান, এটি কোনওটিই ব্যবহার করছে না ORS:

awk 'BEGIN { ORS="" } { print p$0; p=" | " } END { print "\n" }' file > new_file

ব্যাখ্যার জন্য আমার পোস্টটি /unix//a/338121/117599 এ দেখুন

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