স্ট্রিং প্রতিস্থাপনের জন্য অ-লাইন-ভিত্তিক সরঞ্জাম?


13

আমি নতুন প্রশ্নটি অন্য নির্দিষ্ট চরিত্রের পরে যদি ঘটে তবে কীভাবে মুছে ফেলা যায় সে সম্পর্কে আমি একটি প্রশ্ন জিজ্ঞাসা করেছি ।

ইউনিক্স পাঠ্য-প্রক্রিয়াকরণ সরঞ্জামগুলি খুব শক্তিশালী, তবে প্রায় সবগুলিই পাঠ্যের রেখাগুলি নিয়ে কাজ করে, যা ইনপুট উপলভ্য মেমরিটিতে ফিট করে তবে বেশিরভাগ সময় সূক্ষ্ম হয়।

তবে আমি কী করব যদি আমি একটি বিশাল ফাইলে কোনও পাঠ্যক্রমের সিকোয়েন্সটি প্রতিস্থাপন করতে চাই যেখানে কোনও নতুন লাইন থাকে না?

উদাহরণস্বরূপ প্রতিস্থাপন <foobar>সঙ্গে \n<foobar>ইনপুট লাইন বাই লাইন পড়া ছাড়া? (যেহেতু এখানে কেবল একটি লাইন রয়েছে এবং এটি 2.5G অক্ষর দীর্ঘ)।


1
আপনি ব্যবহারের জন্য উন্মুক্ত perlবা python?
ইরুবার

পার্ল ঠিক আছে। আমি সবেমাত্র পেয়েছি gsar( home.online.no/jabtjaberg ) যা আমি চেষ্টা করব।
ম্যাটবিয়ানকো

উত্তর:


12

এই ধরণের সমস্যার মুখোমুখি হওয়ার পরে আমার কাছে প্রথম যেটি ঘটে তা হ'ল রেকর্ড বিভাজকটি পরিবর্তন করা। বেশিরভাগ সরঞ্জামগুলিতে এটি \nডিফল্টরূপে সেট করা থাকে তবে এটি পরিবর্তন করা যায়। উদাহরণ স্বরূপ:

  1. পার্ল

    perl -0x3E -pe 's/<foobar>/\n$&/' file
    

    ব্যাখ্যা

    • -0: এটি হেক্সাডেসিমাল মান অনুসারে একটি অক্ষরে ইনপুট রেকর্ড বিভাজককে সেট করে । এই ক্ষেত্রে, আমি এটির >হেক্স মানটি সেট করছি 3E। সাধারণ বিন্যাসটি হ'ল -0xHEX_VALUE। এটি পরিচালনাযোগ্য অংশগুলিতে লাইনটি ভেঙে ফেলার একটি কৌশল মাত্র।
    • -pe: প্রদত্ত স্ক্রিপ্ট প্রয়োগের পরে প্রতিটি ইনপুট লাইন মুদ্রণ করুন -e
    • s/<foobar>/\n$&/: একটি সহজ বিকল্প। $&যাই হোক না কেন মিলেছে ছিল এই ক্ষেত্রে, হয় <foobar>
  2. awk

    awk '{gsub(/foobar>/,"\n<foobar>");printf "%s",$0};' RS="<" file
    

    ব্যাখ্যা

    • RS="<": ইনপুট রেকর্ড বিভাজক সেট করুন >
    • gsub(/foobar>/,"\n<foobar>"): foobar>সাথে সমস্ত ক্ষেত্রে বিকল্প \n<foobar>। নোট করুন যেহেতু RSসেট করা হয়েছে <, সমস্তই <ইনপুট ফাইল থেকে সরানো হবে (এটি কীভাবে awkকাজ করে) তাই আমাদের মিলবে foobar>(ক ছাড়াই <) এবং এর সাথে প্রতিস্থাপন করা দরকার \n<foobar>
    • printf "%s",$0: প্রতিস্থাপনের পরে বর্তমান "লাইন" মুদ্রণ করুন। $0এটি এখনকার রেকর্ড awkযাতে এটি আগে যা ছিল তা ধরে রাখবে <

আমি এইগুলি একটি কমান্ড দিয়ে তৈরি একটি 2.3 গিগাবাইট, একক-লাইন ফাইলটিতে পরীক্ষা করেছি:

for i in {1..900000}; do printf "blah blah <foobar>blah blah"; done > file
for i in {1..100}; do cat file >> file1; done
mv file1 file

উভয়ই awkএবং perlব্যবহৃত নগদ পরিমাণে স্মৃতি।


আপনি কি কখনও Tie::File perldoc.perl.org/Tie/File.html চেষ্টা করেছেন ? আমি মনে করি Perlবিশাল ফাইলগুলির সাথে ডিল করার সময় এটির সেরা বৈশিষ্ট্য ।
cuonglm

@ জ্ঞাক আমি এটি নিয়ে কিছুটা খেলেছি, হ্যাঁ। তবে i) ওপি ইতিমধ্যে অন্য প্রশ্নের মধ্যে পার্লকে অপছন্দ বলে প্রমাণ করেছে তাই আমি এটিকে সহজ রাখতে চেয়েছিলাম ii) একেবারে প্রয়োজনীয় না হলে বাহ্যিক মডিউলগুলি ব্যবহার করা এড়িয়ে চলার ঝোঁক থাকে iii) টাই :: ফাইল মডিউলটি সিনট্যাক্সকে যথেষ্ট কম করে দেবে পরিষ্কার.
টেরডন

একমত। একটি সামান্য নোট Tie::Fileযেহেতু একটি মূল মডিউল v5.7.3
কিউংলম

9

ঠিক এই উদ্দেশ্যে গাসার (সাধারণ অনুসন্ধান এবং প্রতিস্থাপন) একটি খুব দরকারী সরঞ্জাম।

এই প্রশ্নের বেশিরভাগ উত্তর রেকর্ড-ভিত্তিক সরঞ্জামগুলি এবং বিভিন্ন কৌশল ব্যবহার করে তাদের সমস্যার সাথে খাপ খাইয়ে নিতে, যেমন ডিফল্ট রেকর্ড বিভাজক চরিত্রটিকে এমন কোনও কিছুতে স্যুইচ করা যা ইনপুটটিতে প্রায়শই ঘটতে থাকে বলে মনে হয় যাতে প্রতিটি রেকর্ড পরিচালনা করতে খুব বেশি বড় হয় না।

অনেক ক্ষেত্রে এটি খুব সূক্ষ্ম এবং এমনকি পাঠযোগ্য। আমি সমস্যার সহজেই হতে পারে / দক্ষতার যেমন সর্বত্র-উপলব্ধ সরঞ্জামগুলির সাথে মীমাংসিত পছন্দ করি awk, tr, sedএবং বোর্ন শেল।

বাইনারি অনুসন্ধান করা এবং এলোমেলো বিষয়বস্তু সহ একটি স্বেচ্ছাসেবী বিশাল ফাইলে প্রতিস্থাপন করা এই স্ট্যান্ডার্ড ইউনিক্স সরঞ্জামগুলির জন্য খুব ভাল মানায় না।

আপনারা কেউ কেউ ভাবতে পারেন এটি প্রতারণা করছে তবে আমি দেখছি না যে কাজের জন্য সঠিক সরঞ্জামটি ব্যবহার করা কীভাবে ভুল হতে পারে। এই ক্ষেত্রে এটি একটি সি প্রোগ্রাম বলা হয় gsarযে আওতায় লাইসেন্সকৃত জিপিএল v2 , তাই এটি আমার বেশ একটু তন্ন তন্ন এই খুব দরকারী টুল জন্য এমন কোনো প্যাকেজ নেই অবাক জেন্টু , RedHat , কিংবা উবুন্টু

gsarবায়ার-মুর স্ট্রিং অনুসন্ধান অ্যালগরিদমের বাইনারি রূপ ব্যবহার করে ।

ব্যবহার সোজা-এগিয়ে:

gsar -F '-s<foobar>' '-r:x0A<foobar>'

যেখানে -F"ফিল্টার" মোড অর্থাত্ stdinলেখতে পঠন stdout। ফাইলগুলিতে অপারেট করার পদ্ধতিও রয়েছে। -sঅনুসন্ধানের স্ট্রিং এবং -rপ্রতিস্থাপন নির্দিষ্ট করে । কোলন-নোটেশনটি স্বেচ্ছাচারিত বাইট মানগুলি নির্দিষ্ট করতে ব্যবহৃত হতে পারে।

কেস-সংবেদনশীল মোড সমর্থিত ( -i), তবে নিয়মিত প্রকাশের জন্য কোনও সমর্থন নেই, যেহেতু অ্যালগরিদম অনুসন্ধানের স্ট্রিমটির দৈর্ঘ্যটি অনুসন্ধানের অনুকূলকরণের জন্য ব্যবহার করে।

সরঞ্জামটি কেবল অনুসন্ধানের জন্যও ব্যবহার করা যেতে পারে, কিছুটা grepgsar -bআউটপুট মিলেছে অনুসন্ধান স্ট্রিং এর বাইট অফসেট এবং gsar -lকপি করে প্রিন্ট ফাইলের নাম এবং ম্যাচ সংখ্যা যদি থাকে, মিশ্রন মত একটি বিট grep -lসঙ্গে wc

টুলটি লিখেছিলেন টরমড তজাবার্গ (প্রাথমিক) এবং হান্স পিটার ভার্ন (উন্নতি))


যদি এটি জিপিএল হয় তবে আপনি এটি কোনও ডিসট্রোর জন্য প্যাকেজিংয়ের বিষয়টি বিবেচনা করবেন :)
রিকোমে

1
আসলে আমি এটির জন্য ভদ্রলোক তৈরির বিষয়ে গুরুত্বের সাথে ভাবছি। পাশাপাশি একটি আরপিএমও হতে পারে। তবে আমি এর আগে কখনও .deb প্যাকেজটি তৈরি করি নি, তাই আমি আশা করি যে কেউ আমাকে এটিকে মারবে (কারণ এটি আমার কিছুটা সময় নেবে)।
ম্যাটবিয়ানকো

আমি সন্দেহ করি এটি অনেক সান্ত্বনা তবে ওএস এক্স এর হোমব্রুয়ের সূত্র রয়েছে gsar
ক্রেজিসিম

5

সংকীর্ণ ক্ষেত্রে যেখানে লক্ষ্য এবং প্রতিস্থাপনের স্ট্রিং একই দৈর্ঘ্যের হয়, সেখানে মেমরি ম্যাপিং উদ্ধার করতে পারে। প্রতিস্থাপনটি জায়গায় জায়গায় সঞ্চালনের প্রয়োজন হলে এটি বিশেষভাবে কার্যকর। আপনি মূলত কোনও প্রক্রিয়াটির ভার্চুয়াল মেমোরিতে একটি ফাইল ম্যাপিং করছেন এবং -৪-বিট ঠিকানার জন্য ঠিকানা স্থান বিশাল। নোট করুন যে ফাইলটি একবারে শারীরিক স্মৃতিতে অগত্যা ম্যাপ করা হয় না , সুতরাং মেশিনে উপলব্ধ শারীরিক মেমরির আকারের বেশ কয়েকটি সময় ফাইলগুলি মোকাবেলা করা যেতে পারে।

এখানে একটি পাইথন উদাহরণ যা প্রতিস্থাপন foobarকরেXXXXXX

#! /usr/bin/python
import mmap
import contextlib   
with open('test.file', 'r+') as f:
 with contextlib.closing(mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_WRITE)) as m:
   pos = 0
   pos = m.find('foobar', pos)
   while pos > 0:
    m[pos: pos+len('XXXXXX')] = 'XXXXXX'
    pos = m.find('foobar', pos)

4

এর জন্য অনেকগুলি সরঞ্জাম রয়েছে:

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

tr -dc '[:graph:]' </dev/urandom | dd bs=32 count=1 cbs=8 conv=unblock,sync 2>/dev/null

###OUTPUT###

UI(#Q5\e BKX2?A:Z RAxGm:qv t!;/v!)N

আমি উপরেও ব্যবহার করেছি trকারণ এটি কোনও ASCII বাইটকে অন্য যে কোনও রূপান্তর করতে পরিচালনা করতে পারে (বা এই ক্ষেত্রে কোনও স্থানের ছাপার যোগ্য অক্ষর নয় এমন কোনও ASCII বাইট মুছে ফেলতে পারে)। আজ সকালে আপনার অন্যান্য প্রশ্নের উত্তরে আমি এটি ব্যবহার করেছি , বাস্তবে, যখন আমি করেছি:

tr '>\n' '\n>' | sed 's/^>*//' | tr '\n>' '>\n' 

একই রকম অনেক আছে । এই তালিকাটিতে একটি সর্বনিম্ন সাধারণ-ডিনোমিনেটর উপসেট সরবরাহ করা উচিত যার সাথে আপনি পরিচিত হতে পারেন।

তবে, আমি যদি বাইনারি ফাইলের 2.5 গিগাবাইটে টেক্সট প্রসেসিং করতে যাচ্ছিলাম তবে আমি এটি দিয়ে শুরু করতে পারি od। এটি আপনাকে একটি octal dumpবা অন্য কয়েকটি ফর্ম্যাট দিতে পারে। আপনি সমস্ত ধরণের বিকল্প উল্লেখ করতে পারেন - তবে আমি \Cপালানো বিন্যাসে কেবল প্রতি লাইনে একটি বাইট করব :

আপনি যে ডেটা odপাবেন সেগুলি আপনার নির্দিষ্ট সময় অন্তর নিয়মিত হবে - যেমন আমি নীচে দেখি। তবে প্রথম - আপনার প্রশ্নের উত্তর এখানে:

printf 'first\nnewline\ttab spacefoobar\0null' |
od -A n -t c -v -w1 |
sed 's/^ \{1,3\}//;s/\\$/&&/;/ /bd
     /\\[0nt]/!{H;$!d};{:d
    x;s/\n//g}'

উপর delimits উপরে যে সামান্য বিট \newlines, \0NULLs, \tABS এবং <spaces>যখন সংরক্ষণের \Cবিভেদক জন্য পলান পংক্তি। ব্যবহৃত Hএবং xকার্যাবলী নোট করুন - প্রতিবার sedএকটি ডিলিমিটারের সাথে মুখোমুখি হয়ে এটি এর মেমরি বাফারগুলির সামগ্রীগুলি সরিয়ে দেয়। এইভাবে sedকেবল নির্ভরযোগ্যভাবে ফাইলটি সীমিত করতে যতটা তথ্য রক্ষা করতে হবে এবং বাফারকে ছাড়িয়ে যাবে না - যতক্ষণ না এটি প্রকৃতপক্ষে তার সীমানারগুলির মুখোমুখি হয়। তাই যতদিন এটা আছে জন্য, sedতার ইনপুট প্রক্রিয়া চলতে থাকবে এবং odএটি প্রদান না হওয়া পর্যন্ত এটা encounters অব্যাহত থাকবে EOF

যেমনটি হয়, এর আউটপুটটি এটির মতো দেখাচ্ছে:

first
\nnewline
\ttab
 spacefoobar
\0null

তাই যদি আমি চাই foobar:

printf ... | od ... | sed ... | 
sed 's/foobar/\
&\
/g'

###OUTPUT###

first
\nnewline
\ttab
 space
foobar

\0null

এখন আপনি যদি Cপালিয়ে যাওয়া ব্যবহার করতে চান তবে এটি বেশ সহজ - কারণ sedএরই মধ্যে ডাবল \\ব্যাকস্ল্যাশ এর সমস্ত একক ইনপুট ব্যাকস্ল্যাশ এড়িয়ে গেছে, তাই printfছাড় পেয়েছে xargsআপনার স্পেসিফিকেশনে আউটপুট উত্পাদন করার কোনও সমস্যা নেই। তবে xargs শেলের উদ্ধৃতিগুলি খায় তাই আপনাকে এটি আবার ডাবল উদ্ধৃত করতে হবে:

printf 'nl\ntab\tspace foobarfoobar\0null' |
PIPELINE |
sed 's/./\\&/g' | 
xargs printf %b | 
cat -A

###OUTPUT###

nl$
tab^Ispace $
foobar$
$
foobar$
^@null%

এটি শেল ভেরিয়েবল এবং আউটপুটটিকে অভিন্ন ফ্যাশনে সহজেই সংরক্ষণ করা যেতে পারে। শেষটি তার ইনপুটটিতে প্রতিটি অক্ষরের আগে sedএকটি \ব্যাকস্ল্যাশ সন্নিবেশ করায় এবং এগুলিই।

এটি সর্বদা এটির আগে sedধরে রাখার মতো দেখতে এখানে রয়েছে :

printf 'nl\ntab\tspace foobarfoobar\0null' |
od -A n -t c -v -w1

   n
   l
  \n
   t
   a
   b
  \t
   s
   p
   a
   c
   e

   f
   o
   o
   b
   a
   r
   f
   o
   o
   b
   a
   r
  \0
   n
   u
   l
   l

2

আওক ধারাবাহিক রেকর্ডে পরিচালনা করে। এটি রেকর্ড বিভাজক হিসাবে যে কোনও অক্ষর ব্যবহার করতে পারে (অনেকগুলি প্রয়োগে নাল বাইট ব্যতীত)। কিছু বাস্তবায়ন স্বেচ্ছাসেবী নিয়মিত এক্সপ্রেশন সমর্থন করে (খালি স্ট্রিংয়ের সাথে মেলে না) রেকর্ড বিভাজক হিসাবে, তবে এটি অনস্বাস্থ্যের কারণ হতে পারে কারণ রেকর্ড বিভাজকটি প্রতিটি রেকর্ডের আগেই কাটা হয় $0(জিএনইউ কর্কটি RTরেকর্ড পৃথককে পরিবর্তনশীল করে দেয়) যা বর্তমান রেকর্ডের শেষে থেকে ছিনিয়ে নেওয়া হয়েছিল)। নোট করুন যে printআউটপুট রেকর্ড বিভাজক এর সাথে তার আউটপুটটি সমাপ্ত করে ORSযা ডিফল্টরূপে একটি নতুন লাইন এবং ইনপুট রেকর্ড বিভাজক থেকে স্বতন্ত্রভাবে সেট করে RS

awk -v RS=, 'NR==1 {printf "input up to the first comma: %s\n", $0}'

আপনি কার্যকরভাবে অন্যান্য সরঞ্জাম (রেকর্ড বিভাজক হিসেবে একটি ভিন্ন চরিত্র নির্বাচন করতে পারেন sort, sedযে অক্ষর দিয়ে নতুন লাইন সোয়াপিং দ্বারা, ...) tr

tr '\n,' ',\n' |
sed 's/foo/bar/' |
sort |
tr '\n,' ',\n'

অনেকগুলি জিএনইউ টেক্সট ইউটিলিটিগুলি বিভাজক হিসাবে একটি নতুন লাইনের পরিবর্তে নাল বাইট ব্যবহার করে সমর্থন করে।

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