গ্রেপ কোন ফাইলকে বাইনারি হিসাবে বিবেচনা করে?


185

আমার বাক্সে আমার উইন্ডোজ সিস্টেম থেকে কিছু ডাটাবেস ডাম্প রয়েছে। তারা পাঠ্য ফাইল। আমি তাদের মাধ্যমে গ্রেপ করতে সাইগউইন ব্যবহার করছি। এগুলি সরল পাঠ্য ফাইল হিসাবে প্রদর্শিত হবে; আমি এগুলি নোটপ্যাড এবং ওয়ার্ডপ্যাডের মতো পাঠ্য সম্পাদকগুলি দিয়ে খুলি এবং সেগুলি সুস্পষ্ট দেখায়। যাইহোক, আমি যখন তাদের উপর গ্রেপ চালাব, এটি বলবে binary file foo.txt matches

আমি লক্ষ্য করেছি যে ফাইলগুলিতে কিছু আসকি NULঅক্ষর রয়েছে, যা আমি বিশ্বাস করি যে ডেটাবেস ডাম্প থেকে নিদর্শন।

সুতরাং গ্রিপ কি এই ফাইলগুলি বাইনারি হিসাবে বিবেচনা করে? NULচরিত্র? ফাইল সিস্টেমে কি কোনও পতাকা রয়েছে? আমাকে লাইন ম্যাচগুলি দেখানোর জন্য গ্রেপ পেতে আমার কী পরিবর্তন করতে হবে?


2
--null-dataNULডিলিমিটার হলে কার্যকর হতে পারে ।
স্টিভ-ও

উত্তর:


125

যদি NULফাইলের কোথাও কোনও অক্ষর থাকে তবে গ্রেপ এটিকে বাইনারি ফাইল হিসাবে বিবেচনা করবে।

cat file | tr -d '\000' | yourgrepপ্রথমে সমস্ত শূন্যতা দূর করতে, এবং তারপরে ফাইলের মাধ্যমে অনুসন্ধান করার জন্য এর মতো কোনও কাজ হতে পারে ।


149
... বা ব্যবহার -a/ --text, কমপক্ষে জিএনইউ গ্রেপ সহ।
ডারোবার্ট

1
@ এরোবার্ট: আসলে, কিছু (পুরানো) সিস্টেমে, গ্রেপ লাইনগুলি দেখুন, তবে এর আউটপুটটি প্রতিটি মিলের লাইনটি প্রথমে NULছাঁটাবে (সম্ভবত এটি সি এর প্রিন্টফকে কল করে এবং এটি ম্যাচিং লাইন দেয়?) এই জাতীয় সিস্টেমে একটি grep cmd .sh_history'সেন্টিমিডি' মিলিত লাইন যতটা খালি লাইন ফিরে আসবে, sh_history এর প্রতিটি লাইনের প্রতিটি লাইনের শুরুতে একটি নির্দিষ্ট বিন্যাস রয়েছে NUL। (তবে আপনার মন্তব্য "কমপক্ষে জিএনইউ গ্রেপ এ" সম্ভবত সত্য হয়ে গেছে test পরীক্ষার জন্য আমার কাছে এখনই হাত নেই, তবে আমি আশা করি তারা এগুলি সুন্দরভাবে পরিচালনা করবে)
অলিভিয়ার ডুলাক

4
কোনও NUL চরিত্রের উপস্থিতি কি একমাত্র মানদণ্ড? আমি এটাকে সন্দেহ করি. এটি সম্ভবত তার চেয়ে বেশি স্মার্ট। এসকিআই 32-126 রেঞ্জের বাইরে যে কোনও কিছু পড়ার বিষয়টি আমার অনুমান, তবে আমাদের নিশ্চিত হওয়ার জন্য উত্স কোডটি দেখতে হবে।
মাইকেল মার্টিনেজ

2
আমার তথ্যটি নির্দিষ্ট গ্রেপ উদাহরণের ম্যান পৃষ্ঠা থেকে ছিল। বাস্তবায়ন সম্পর্কে আপনার মন্তব্য বৈধ, উত্স ট্রাম্প ডক্স।
বিবাজা 42

2
আমার একটি ফাইল ছিল যা grepসাইগউইনে বাইনারি হিসাবে বিবেচিত হয়েছিল কারণ এটিতে নিয়মিত ASCII হাইফেন / বিয়োগ (0x2 ডি) এর পরিবর্তে দীর্ঘ ড্যাশ (0x96) ছিল। আমার ধারণা এই উত্তরটি ওপির সমস্যার সমাধান করেছে, তবে এটি অসম্পূর্ণ বলে মনে হচ্ছে।
cp.engr

121

grep -a আমার জন্য কাজ করেছেন:

$ grep --help
[...]
 -a, --text                equivalent to --binary-files=text

4
এটি সেরা, সর্বনিম্ন ব্যয়বহুল উত্তর আইএমও।
পাইডসাইনার

তবে পসিক্স অনুগত নয়
মাত্তেও

21

আপনি ব্যবহার করতে পারেন stringsযেকোনো ফাইল থেকে টেক্সট কন্টেন্ট এবং তারপর এটি নল মাধ্যমে বের করে আনতে ইউটিলিটি grep, এরকম: strings file | grep pattern


2
আংশিক দূষিত হতে পারে এমন লগ ফাইলগুলি গ্রেপিংয়ের জন্য আদর্শ
হ্যানস আর

হ্যাঁ, কখনও কখনও বাইনারি মিশ্র লগিংও ঘটে। এটা ভাল.
sdkks

13

জিএনইউ গ্রেপ 2.24 আরটিএফএস

উপসংহার: কেবলমাত্র 2 এবং 2 টি ক্ষেত্রে:

  • NUL, যেমন printf 'a\0' | grep 'a'

  • C99 অনুসারে এনকোডিংয়ের ত্রুটি mbrlen(), যেমন:

    export LC_CTYPE='en_US.UTF-8'
    printf 'a\x80' | grep 'a'
    

    কারণ \x80কোনও ইউটিএফ -8 ইউনিকোড পয়েন্টের প্রথম বাইট হতে পারে না: ইউটিএফ -8 - বিবরণ | en.wikipedia.org

তদ্ব্যতীত, স্টাফেন চেজেলাস দ্বারা উল্লিখিত গ্রাইপ কোন ফাইলকে বাইনারি হিসাবে বিবেচনা করে? | ইউনিক্স এবং লিনাক্স স্ট্যাক এক্সচেঞ্জ , এই চেকগুলি কেবলমাত্র টোডো দৈর্ঘ্যের প্রথম বাফার রিড পর্যন্ত সম্পন্ন হয়।

শুধুমাত্র প্রথম বাফার পর্যন্ত পড়া

সুতরাং যদি কোনও NUL বা এনকোডিং ত্রুটি খুব বড় ফাইলের মাঝখানে ঘটে তবে তা কোনওভাবেই গ্রেপ করা যেতে পারে।

আমি ধারণা করি এটি পারফরম্যান্সের কারণে।

যেমন: এটি লাইনটি মুদ্রণ করে:

printf '%10000000s\n\x80a' | grep 'a'

তবে এটি করে না:

printf '%10s\n\x80a' | grep 'a'

প্রকৃত বাফার আকারটি ফাইলটি কীভাবে পড়বে তার উপর নির্ভর করে। যেমন তুলনা:

export LC_CTYPE='en_US.UTF-8'
(printf '\n\x80a') | grep 'a'
(printf '\n'; sleep 1; printf '\x80a') | grep 'a'

এর সাথে sleep, প্রথম লাইনটি কেবল 1 বাইট দীর্ঘ হলেও পাকাপাকিভাবে গ্রেপ হয়ে যায় কারণ প্রক্রিয়াটি ঘুমাতে যায়, এবং দ্বিতীয় পঠনটি ফাইলটি বাইনারি রয়েছে কিনা তা পরীক্ষা করে না।

RTFS

git clone git://git.savannah.gnu.org/grep.git 
cd grep
git checkout v2.24

স্ট্যাডার ত্রুটি বার্তাটি এনকোড করা হয়েছে তা সন্ধান করুন:

git grep 'Binary file'

আমাদের এখানে নিয়ে যায় /src/grep.c:

if (!out_quiet && (encoding_error_output
                    || (0 <= nlines_first_null && nlines_first_null < nlines)))
    {
    printf (_("Binary file %s matches\n"), filename);

যদি এই ভেরিয়েবলগুলি ভালভাবে নামকরণ করা হয়, তবে আমরা মূলত সিদ্ধান্তে পৌঁছে যাই।

encoding_error_output

দ্রুত গ্রেপিং encoding_error_outputশোগুলি দেখায় যে এটি কেবলমাত্র কোড পাথ যা এটি পরিবর্তন করতে পারে buf_has_encoding_errors:

clen = mbrlen (p, buf + size - p, &mbs);
if ((size_t) -2 <= clen)
  return true;

তাহলে ঠিক man mbrlen

nlines_first_null এবং nlines

হিসাবে সূচনা:

intmax_t nlines_first_null = -1;
nlines = 0;

সুতরাং একটি নাল পাওয়া 0 <= nlines_first_nullগেলে সত্য হয়ে যায়।

টোডো কখন nlines_first_null < nlinesমিথ্যা হতে পারে? অলস হয়ে গেলাম।

POSIX

বাইনারি বিকল্পগুলি গ্রেপ সংজ্ঞায়িত করে না - একটি প্যাটার্নের জন্য একটি ফাইল অনুসন্ধান করুন pubs.opengroup.org , এবং GNU গ্রেপ এটি নথিভুক্ত করে না, সুতরাং আরটিএফএসই একমাত্র উপায়।


1
চিত্তাকর্ষক ব্যাখ্যা!
ব্যবহারকারী 394

2
মনে রাখবেন যে বৈধ ইউটিএফ -8 এর জন্য চেকটি কেবলমাত্র ইউটিএফ -8 লোকেলগুলিতে ঘটে। এছাড়াও নোট করুন যে চেকটি কেবলমাত্র ফাইল থেকে পঠিত প্রথম বাফারে করা হয় যা নিয়মিত ফাইলের জন্য আমার সিস্টেমে 32768 বাইট বলে মনে হয় তবে পাইপ বা সকেটের জন্য এক বাইটের চেয়ে ছোট হতে পারে। উদাহরণস্বরূপ (printf '\n\0y') | grep yসঙ্গে তুলনা করুন (printf '\n'; sleep 1; printf '\0y') | grep y
স্টাফেন চেজেলাস

@ স্টাফেনচাজলাস "নোট করুন যে বৈধ ইউটিএফ -8 জন্য চেকটি কেবল ইউটিএফ -8 লোকালেই ঘটে": আপনার export LC_CTYPE='en_US.UTF-8'উদাহরণটি যেমন আমার উদাহরণ হিসাবে বা অন্য কিছু? বুফ পড়লেন: উত্তরের উদাহরণ, উত্তর যুক্ত হয়েছে। আপনি স্পষ্টতই আমার চেয়ে বেশি উত্সটি পড়েছেন, সেই হ্যাকার কোয়ানদের মনে করিয়ে দিয়েছেন "ছাত্রটি আলোকিত হয়েছিল" :-)
সিওরো সান্তিলি r 改造 中心 法轮功 六四 六四 r


1
@CiroSantilli 巴拿馬 文件 六四 事件 G আপনি GNU গ্রেপের কোন সংস্করণের বিপরীতে পরীক্ষা করেছেন?
jrw32982

6

আমার একটি পাঠ্য ফাইল হঠাৎ করে গ্রেপ দ্বারা বাইনারি হিসাবে দেখা হচ্ছিল:

$ file foo.txt
foo.txt: ISO-8859 text

সমাধানটি এটি ব্যবহার করে রূপান্তর করা হয়েছিল iconv:

iconv -t UTF-8 -f ISO-8859-1 foo.txt > foo_new.txt

1
আমার সাথেও এটি ঘটেছিল। বিশেষত, কারণটি ছিল একটি ISO-8859-1- এনকোডযুক্ত নন-ব্রেকিং স্পেস, যা ফাইলটিতে অনুসন্ধানের জন্য গ্রাইপ পাওয়ার জন্য আমাকে একটি নিয়মিত স্থান দিয়ে প্রতিস্থাপন করতে হয়েছিল।
গ্যালাসিও

4
গ্রেপ 2.21 ISO-8859 পাঠ্য ফাইলগুলি বাইনারি হওয়ার মতো আচরণ করে, গ্রেপ কমান্ডের আগে রফতানি LC_ALL = C যুক্ত করুন।
নেটওয়াটার

@ নেটওয়াটার ধন্যবাদ! এটি উদাহরণস্বরূপ যদি আপনার কোনও পাঠ্য-ফাইলে মলারের মতো কিছু থাকে। এটি 0xFCহেক্সাডেসিমাল, সুতরাং পরিসরের গ্রেপের বাইরে utf8 (আপ 0x7F) আশা করা উচিত । প্রিন্টফ 'a \ x7F' এর সাথে চেক করুন উপরে সিওরো বর্ণিত হিসাবে গ্রেপ 'এ' করুন।
অ্যান ভ্যান রসম

5

ফাইলটি টাইপ নির্ধারণের জন্য কমান্ড ব্যবহার করে এমন ফাইল /etc/magicবা /usr/share/misc/magicক্রমের একটি তালিকা রয়েছে file

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

grepলিনাক্সে --binary-filesবা বাইনারি ফাইলগুলি হ্যান্ডেল করার মতো কিছু বিকল্প রয়েছে বা-U / --binary


আরও স্পষ্টভাবে, C99 এর অনুসারে এনকোডিংয়ের ত্রুটি mbrlen()। উদাহরণ এবং উত্স ব্যাখ্যা এখানে: unix.stackexchange.com/a/276028/32558
সিরো সান্তিলি

2

আমার এক শিক্ষার্থীর এই সমস্যা ছিল। ভিতরে একটি বাগ grepআছে Cygwin। যদি ফাইলটিতে অ-এস্কি অক্ষর থাকে grepএবং egrepএটি বাইনারি হিসাবে দেখেন।


এটি কোনও বাগের মতো নয়, বৈশিষ্ট্যের মতো শোনাচ্ছে। এটি নিয়ন্ত্রণ করার জন্য একটি কমান্ড-লাইন অপশন রয়েছে বিশেষত দেওয়া হয়েছে (-a / --text)
উইল শেপার্ড

2

আসলে "গ্রেপ কোনও ফাইলকে বাইনারি হিসাবে বিবেচনা করে?" এই প্রশ্নের উত্তর দিয়ে আপনি ব্যবহার করতে পারেন iconv:

$ iconv < myfile.java
iconv: (stdin):267:70: cannot convert

আমার ক্ষেত্রে স্প্যানিশ অক্ষর রয়েছে যা পাঠ্য সম্পাদকগুলিতে সঠিকভাবে প্রদর্শিত হয়েছিল তবে গ্রেপ এগুলিকে বাইনারি হিসাবে বিবেচনা করেছিল; iconvআউটপুট আমাকে এই অক্ষরের রেখা এবং কলাম নম্বরগুলিতে ইঙ্গিত করেছে

NULচরিত্রগুলির ক্ষেত্রে, iconvএগুলি স্বাভাবিক হিসাবে বিবেচনা করবে এবং এ জাতীয় আউটপুট প্রিন্ট করবে না তাই এই পদ্ধতিটি উপযুক্ত নয়


1

আমারও একই সমস্যা ছিল। আমি vi -b [filename]যোগ করা অক্ষর দেখতে ব্যবহৃত । আমি নিয়ন্ত্রণের অক্ষর খুঁজে পেয়েছি ^@এবং ^M। তারপরে vi :1,$s/^@//gতে ^@অক্ষরগুলি সরাতে টাইপ করুন । এই কমান্ডটির জন্য পুনরাবৃত্তি করুন ^M

সতর্কতা: "নীল" নিয়ন্ত্রণের অক্ষরগুলি পেতে Ctrl+ vতারপরে Ctrl+ Mবা Ctrl+ টিপুন @। তারপরে সংরক্ষণ করুন এবং প্রস্থান করুন vi।

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