Grep ගොනුවක් ද්විමය ලෙස සලකන්නේ කුමක් නිසාද?


203

මගේ කොටුවේ වින්ඩෝස් පද්ධතියකින් දත්ත සමුදායන් කිහිපයක් තිබේ. ඒවා පෙළ ගොනු ය. මම සිග්වින් පාවිච්චි කරන්නේ ඒවා හරහා යන්න. මේවා සරල පෙළ ලිපිගොනු ලෙස පෙනේ; නොට්පෑඩ් සහ වර්ඩ් පෑඩ් වැනි පෙළ සංස්කාරකවරුන් සමඟ මම ඒවා විවෘත කරමි. කෙසේ වෙතත්, මම ඔවුන් මත grep ධාවනය කරන විට, එය කියනු binary file foo.txt matchesඇත.

ලිපිගොනු වල NULදත්ත ගබඩාවේ ඇති කෞතුක වස්තු යැයි මම විශ්වාස කරන සමහර ඇස්කි අක්ෂර අඩංගු බව මම දැක ඇත්තෙමි .

ඉතින් grep මෙම ලිපිගොනු ද්විමය ලෙස සලකන්නේ කුමක් නිසාද? මෙම NULචරිතය? ගොනු පද්ධතියේ ධජයක් තිබේද? රේඛා ගැලපීම් මට පෙන්වීමට grep ලබා ගැනීමට මා වෙනස් කළ යුත්තේ කුමක්ද?


3
--null-dataNULපරිසීමකය නම් ප්‍රයෝජනවත් විය හැකිය .
ස්ටීව්-ඕ

Answers:


139

කාලයක් පවතින්නේ නම් NULගොනුව තුල චරිතය ඕනෑම තැනක, අයිතිය සුරකියි ද්විමය ගොනුව ලෙස සලකා ඇත.

එහි මේ වගේ සලසන වක් මගක් විය හැකි cat file | tr -d '\000' | yourgrepපළමු කොට සියලු ශූන්ය තුරන් කිරීම සඳහා, පසුව ගොනු සෙවීම.


161
... හෝ අවම වශයෙන් GNU grep සමඟ -a/ භාවිතා කරන්න --text.
ඩෙරොබට්

1
roderobert: ඇත්ත වශයෙන්ම, සමහර (පැරණි) පද්ධතිවල, රේඛා බලන්න, නමුත් එහි ප්‍රතිදානය සෑම ගැලපෙන NULරේඛාවක්ම මුලින් කප්පාදු කරනු ඇත (බොහෝ විට එය C හි printf ලෙස හඳුන්වන අතර එයට ගැලපෙන රේඛාව ලබා දෙයිද?). එවැනි පද්ධතියක් තුළ grep cmd .sh_history'cmd' ට ගැලපෙන රේඛා ඇති තරම් හිස් රේඛා නැවත ලැබෙනු ඇත, සෑම sh_history පේළියකටම එක් එක් පේළියේ ආරම්භයේ දී නිශ්චිත ආකෘතියක් ඇත NUL. (. නමුත් ඔබේ බොහෝ විට සැබෑ වී තිබෙන මම පරීක්ෂා දැන් අත එකක් නැහැ, නමුත් මම ඔවුන් අවසරයෙන් මෙම හැසිරවිය බලාපොරොත්තු "අවම වශයෙන් GNU අයිතිය සුරකියි මත" අදහස්)
ඔලිවර් Dulac

4
NUL අක්ෂරයක් පැවතීම එකම නිර්ණායකයක්ද? මම එය සැක කළා. එය බොහෝ විට ඊට වඩා දක්ෂයි. Ascii 32-126 පරාසයෙන් පිටත වැටෙන ඕනෑම දෙයක් මගේ අනුමානය වනු ඇත, නමුත් අපට සහතික වීමට ප්‍රභව කේතය දෙස බැලිය යුතුය.
මයිකල් මාටිනස්

2
මගේ තොරතුරු විශේෂිත ග්‍රෙප් උදාහරණයේ මෑන් පිටුවෙන් විය. ක්‍රියාත්මක කිරීම පිළිබඳ ඔබේ අදහස වලංගු වේ, ප්‍රභව තුරුම්පුව.
bbaja42

2
grepසාමාන්‍ය ASCII හයිපන් / us ණ (0x2d) වෙනුවට දිගු ඉරක් (0x96) ඇති බැවින් සිග්වින් ද්විමය ලෙස සලකන ගොනුවක් මා සතුව තිබුණි . මෙම පිළිතුර OP හි ගැටළුව විසඳූ බව මම අනුමාන කරමි, නමුත් එය අසම්පූර්ණ බව පෙනේ.
cp.engr

141

grep -a මා වෙනුවෙන් වැඩ කළා:

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

6
IMO හි හොඳම, අඩුම මිල පිළිතුර මෙයයි.
pydsigner

1
නමුත් POSIX අනුකූල නොවේ
Matteo

1
එය එසේ නොවීමට හේතුව පැහැදිලි කිරීමට ඔබ කැමතිද? මෙම පිළිතුර විකල්පයක් ලෙස සොයා ගන්නා අප සැමට පැහැදිලි කිරීම හොඳය. ස්තූතියි :).
ivanleoncz

22

ඔබ භාවිතා කළ හැකිය strings, කිසිදු ගොනු සිට පෙළ අන්තර්ගතයට උපුටා පසුව හරහා නල එය උපයෝගීතා grepමේ වගේ,: strings file | grep pattern.


2
අර්ධ වශයෙන් දූෂිත විය හැකි ලොග් ගොනු අතුගා දැමීම සඳහා වඩාත් සුදුසුය
හැනස් ආර්.

ඔව්, සමහර විට ද්විමය මිශ්‍ර ල ging ු-සටහන් ද සිදු වේ. මේක හොඳයි.
sdkks

13

GNU grep 2.24 RTFS

නිගමනය: නඩු 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

තවද, ස්ටෙෆාන් චසෙලාස් සඳහන් කළ පරිදි grep ගොනුවක් ද්විමය ලෙස සලකන්නේ කුමක් ද? | යුනික්ස් සහ ලිනක්ස් ස්ටැක් එක්ස්චේන්ජ් , එම චෙක්පත් සිදු කරනු ලබන්නේ ටෝඩෝ දිග කියවන පළමු බෆරය දක්වා පමණි.

පළමු බෆරය කියවීම දක්වා පමණි

එබැවින් ඉතා විශාල ගොනුවක් මධ්‍යයේ 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 බයිට පමණක් වුවද grep කිරීමට සමත් වී යයි.

RTFS

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

Stderr දෝෂ පණිවිඩය කේතනය කර ඇති ස්ථානය සොයා ගන්න:

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එය සත්‍ය වේ.

TODO nlines_first_null < nlinesකවදා හෝ අසත්‍ය විය හැක්කේ කවදාද? මට කම්මැලි විය.

පොසික්ස්

ද්විමය විකල්ප grep නිර්වචනය නොකරයි - රටාවක් සඳහා ගොනුවක් සොයන්න | pubs.opengroup.org , සහ GNU grep එය ලේඛනගත නොකරයි, එබැවින් RTFS එකම ක්‍රමයයි.


1
ආකර්ෂණීය පැහැදිලි කිරීම!
user394

2
වලංගු UTF-8 සඳහා වන චෙක්පත සිදුවන්නේ UTF-8 ස්ථානවල පමණක් බව සලකන්න. චෙක්පත සිදු කරනු ලබන්නේ ගොනුවෙන් කියවන පළමු බෆරය මත පමණක් වන අතර එය සාමාන්‍ය ගොනුවක් සඳහා මගේ පද්ධතියේ බයිට් 32768 ක් බව පෙනේ, නමුත් පයිප්පයක් හෝ සොකට් එකක් සඳහා එක් බයිට් එකක් තරම් කුඩා විය හැකිය. සංසන්දනය (printf '\n\0y') | grep yසමග (printf '\n'; sleep 1; printf '\0y') | grep yඋදාහරණයක්.
ස්ටෙෆාන් චසෙලාස්

@ ස්ටෙෆාන් චැසෙලාස් "වලංගු යූටීඑෆ් -8 සඳහා වන චෙක්පත සිදුවන්නේ යූටීඑෆ් -8 ස්ථානවල පමණක් බව සලකන්න": ඔබ අදහස් කරන්නේ export LC_CTYPE='en_US.UTF-8'මගේ උදාහරණයේ හෝ වෙනත් දෙයක් ගැනද? බුෆ් කියවීම: විස්මිත උදාහරණය, ​​පිළිතුරු සඳහා එකතු කරන ලදි. ඔබ මට වඩා පැහැදිලිවම මූලාශ්‍රය කියවා ඇති අතර, එම හැකර් කෝන්වරුන් මට මතක් කර දෙයි “ශිෂ්‍යයා බුද්ධිමත් විය” :-)
සීරෝ සැන්ටිලි 冠状 病毒 审查 六四 法轮功 法轮功

1
මම වැඩි විස්තරයක් බැලුවේ නැත, නමුත් ඉතා මෑතකදී සිදු කළෙමි
ස්ටෙෆාන් චසෙලාස්

1
@CiroSantilli 巴拿馬 文件 六四 事件 G ඔබ GNU grep හි කුමන අනුවාදයට එරෙහිව අත්හදා බැලුවාද?
jrw32982

6

මගේ එක් පෙළ ගොනුවක් හදිසියේම grep විසින් ද්විමය ලෙස දැකිය හැකි විය:

$ 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
grep 2.21 ISO-8859 පෙළ ගොනු ද්විමය ලෙස සලකයි, grep විධානයට පෙර අපනයන LC_ALL = C එක් කරන්න.
නෙටවටර්

ස්තූතියි! මෙය ඔබට පෙළ ගොනුවක මුලර් වැනි දෙයක් තිබේ නම් එය එසේ වේ. එය 0xFCෂඩාස්රාකාර වේ, එබැවින් grep පරාසයෙන් පිටත utf8 (දක්වා 0x7F) බලාපොරොත්තු වේ. Printf 'a \ x7F' | සමඟ පරීක්ෂා කරන්න සීරෝ ඉහත විස්තර කළ පරිදි grep 'a'.
ne න් වැන් රොසුම්

5

ගොනුව /etc/magicහෝ ගොනු වර්ගය තීරණය කිරීම සඳහා /usr/share/misc/magicවිධානය fileභාවිතා කරන අනුක්‍රමික ලැයිස්තුවක් ඇත .

ද්විමය යනු ආපසු හැරවීමේ විසඳුමක් විය හැකි බව සලකන්න . සමහර විට අමුතු කේතීකරණ සහිත ලිපිගොනු ද්විමය ලෙසද සැලකේ.

grepලිනක්ස් හි --binary-filesහෝ වැනි ද්විමය ගොනු හැසිරවීමට විකල්ප කිහිපයක් ඇත-U / --binary


වඩාත් නිවැරදිව, C99 ට අනුව කේතීකරණ දෝෂයකි mbrlen(). උදාහරණ සහ මූලාශ්‍ර අර්ථ නිරූපණය: unix.stackexchange.com/a/276028/32558
සිරෝ සැන්ටිලි 冠状 病毒 审查 六四 法轮功 法轮功

2

මගේ එක් සිසුවෙකුට මෙම ගැටලුව ඇති විය. ඇතුළත දෝෂයක් grepතිබේ Cygwin. ගොනුව ascii නොවන අක්ෂර ඇත, නම් grepසහ egrepද්විමය සංඛ්යාව ලෙස එය බලන්න.


එය දෝෂයක් නොව අංගයක් ලෙස පෙනේ. එය පාලනය කිරීම සඳහා විධාන රේඛා විකල්පයක් ඇත (-a / --text)
Will Sheppard

2

"Grep ගොනුවක් ද්විමය ලෙස සලකන්නේ කුමක් නිසාද?" යන ප්‍රශ්නයට සැබවින්ම පිළිතුරු සැපයීම, ඔබට මෙය භාවිතා කළ හැකිය iconv:

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

මගේ කාරණයේදී ස්පා Spanish ් characters අක්ෂර පෙළ සංස්කාරකවරුන් තුළ නිවැරදිව පෙන්වන නමුත් ඒවා ද්විමය ලෙස සලකන ලදී. iconvප්‍රතිදානය එම අක්ෂරවල රේඛාව සහ තීරු අංක වෙත මා යොමු කළේය

NULඅක්ෂර සම්බන්ධයෙන් ගත් කල , iconvඒවා සාමාන්‍ය ලෙස සලකනු ඇති අතර එම ප්‍රතිදානය මුද්‍රණය නොකරනු ඇත, එබැවින් මෙම ක්‍රමය සුදුසු නොවේ


1

මටත් ඒ වගේ ප්‍රශ්නයක් තිබුණා. vi -b [filename]එකතු කළ අක්ෂර මම දැකීමට පුරුදුව සිටියෙමි . මම පාලනය චරිත සොයා ^@හා ^M. :1,$s/^@//gඉවත් කිරීමට vi ටයිප් කරන්න^@අක්ෂර . සඳහා මෙම විධානය නැවත කරන්න ^M.

අවවාදයයි: "නිල්" පාලක අක්‍ෂර ලබා ගැනීම සඳහා Ctrl+ vඉන්පසු Ctrl+ Mහෝ Ctrl+ ඔබන්න @. ඉන්පසු සුරකින්න සහ පිටවන්න vi.

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.