কোনও রূপান্তর ছাড়াই বাইট বাক্যে কপি করার জন্য আমি কীভাবে বাইনারে বাইনারি নিয়ে কাজ করতে পারি?


14

আমি উচ্চাভিলাষী কারণে অগণিত কারণে একটি সি ++ কোডটিকে ব্যাশে অনুবাদ করার চেষ্টা করছি।

এই কোডটি আমার সাব-ফিল্ডের সাথে সুনির্দিষ্ট একটি ফাইল টাইপ পড়ে এবং পরিচালনা করে যা বাইনারিতে সম্পূর্ণরূপে লিখিত এবং কাঠামোগত। আমার প্রথম বাইনারি সম্পর্কিত টাস্কটি হাইডারের প্রথম 988 বাইট হুবহু হ'ল অনুলিপি করা এবং এগুলিকে একটি আউটপুট ফাইলে রেখে দেওয়া উচিত যা আমি বাকী তথ্য উত্পন্ন করার সাথে সাথে লিখতে পারি।

আমি নিশ্চিত যে আমার বর্তমান সমাধানটি কাজ করছে না এবং বাস্তবতাগতভাবে এটি নির্ধারণের জন্য আমি কোনও ভাল উপায় বের করতে পারি নি। সুতরাং এটি আসলে সঠিকভাবে লেখা থাকলেও, আমার নিশ্চিত হওয়া দরকার যে আমি কীভাবে এটি পরীক্ষা করব!

আমি এখনই এটি করছি:

hdr_988=`head -c 988 ${inputFile}`
echo -n "${hdr_988}" > ${output_hdr}
headInput=`head -c 988 ${inputTrack} | hexdump`
headOutput=`head -c 988 ${output_hdr} | hexdump`
if [ "${headInput}" != "${headOutput}" ]; then echo "output header was not written properly.  exiting.  please troubleshoot."; exit 1; fi

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

ব্যাশে এটি করার আরও ভাল উপায় আছে কি? কোনও ফাইল ভারব্যাটিয়ামে অনুলিপি করার জন্য আমি কী কেবল দেশীয়-বাইনারিগুলিতে বাইনারি বাইটগুলি অনুলিপি / পড়তে পারি? (এবং আদর্শভাবে ভেরিয়েবল হিসাবে সংরক্ষণ করার জন্য)।


আপনি ব্যবহার করতে পারেন ddপৃথক বাইট (তার সেটিং কপি করতে countকরতে 1)। যদিও সেগুলি সংরক্ষণ করার বিষয়ে আমি নিশ্চিত নই।
DDPWNAGE

সি পথে বাশ করবেন না, এটি অনেক মাথাব্যাথা তৈরি করবে। পরিবর্তে যথাযথ বাশ নির্মাণ ব্যবহার করুন
ফেরিবিগ

উত্তর:


22

শেল স্ক্রিপ্টগুলিতে নিম্ন স্তরে বাইনারি ডেটা নিয়ে কাজ করা সাধারণত একটি খারাপ ধারণা।

bashভেরিয়েবলগুলি বাইট ০ থাকতে পারে না 0. zshএকমাত্র শেল যা এই বাইটটিকে তার ভেরিয়েবলগুলিতে সঞ্চয় করতে পারে।

যে কোনও ক্ষেত্রে, কমান্ড আর্গুমেন্ট এবং এনভায়রনমেন্ট ভেরিয়েবলগুলি সেই বাইটগুলি ধারণ করতে পারে না কারণ সেগুলি execveসিস্টেম কলটিতে পাস করা NUL ডিলিমিট স্ট্রিং ।

এটিও নোট করুন:

var=`cmd`

বা এর আধুনিক রূপ:

var=$(cmd)

এর আউটপুট থেকে সমস্ত পেছনের নতুন লাইন অক্ষর ফেলা হয় cmd। সুতরাং, যদি বাইনারি আউটপুট 0xa বাইটে শেষ হয় তবে এটি সঞ্চিত অবস্থায় ম্যাঙ্গাল করা হবে $var

এখানে, উদাহরণস্বরূপ, আপনাকে এনকোড করা ডেটা সংরক্ষণ করতে হবে xxd -p

hdr_988=$(head -c 988 < "$inputFile" | xxd -p)
printf '%s\n' "$hdr_988" | xxd -p -r > "$output_hdr"

আপনি সাহায্যকারী ফাংশনগুলি যেমন সংজ্ঞায়িত করতে পারেন:

encode() {
  eval "$1"='$(
    shift
    "$@" | xxd -p  -c 0x7fffffff
    exit "${PIPESTATUS[0]}")'
}

decode() {
  printf %s "$1" | xxd -p -r
}

encode var cat /bin/ls &&
  decode "$var" | cmp - /bin/ls && echo OK

xxd -pআউটপুট স্পেস দক্ষ নয় কারণ এটি 2 বাইটে 1 বাইট এনকোড করে, তবে এটির সাথে ম্যানিপুলেশনগুলি করা সহজ করে তোলে (অংশগুলি বের করে, অংশগুলি বের করে)। base64এটি এমন একটি যা 4 এ 3 বাইট এনকোড করে তবে এর সাথে কাজ করা সহজ নয়।

ksh93শেল একটি builtin এনকোডিং ফরম্যাট (ব্যবহার করা হয় base64) যা আপনি তার সাথে ব্যবহার করতে পারেন readএবং printf/ printইউটিলিটি:

typeset -b var # marked as "binary"/"base64-encoded"
IFS= read -rn 988 var < input
printf %B var > output

এখন, যদি শেল বা এনভি ভেরিয়েবলগুলির মাধ্যমে কোনও ট্রানজিট বা কমান্ড আর্গুমেন্ট না থাকে তবে আপনি যতক্ষণ যে ইউটিলিটিগুলি ব্যবহার করেন কোনও বাইট মান হ্যান্ডেল করতে পারে ততক্ষণ আপনার উচিত ঠিক। তবে মনে রাখবেন যে পাঠ্য ইউটিলিটির জন্য, বেশিরভাগ নন-জিএনইউ বাস্তবায়নগুলি NUL বাইটগুলি পরিচালনা করতে পারে না এবং আপনি মাল্টি-বাইট অক্ষরগুলির সমস্যা এড়াতে লোকেল সিটিতে ঠিক করতে চাইবেন। সর্বশেষ অক্ষরটি একটি নতুন লাইন চরিত্র না হয়েও সমস্যাগুলির পাশাপাশি খুব দীর্ঘ লাইনও তৈরি করতে পারে (দুটি 0xa বাইটের মধ্যে বাইটগুলির ক্রম যা এর চেয়ে দীর্ঘ হয় LINE_MAX)।

head -cএটি যেখানে পাওয়া যায় তা এখানে ঠিক থাকা উচিত, কারণ এটি বাইটগুলির সাথে কাজ করা বোঝায় এবং ডেটাটিকে পাঠ্য হিসাবে বিবেচনা করার কোনও কারণ নেই। সুতরাং

head -c 988 < input > output

্রত. অনুশীলনে কমপক্ষে GNU, FreeBSD এবং ksh93 অন্তর্নির্মিত বাস্তবায়ন ঠিক আছে। পসিক্স -cবিকল্পটি নির্দিষ্ট করে না , তবে বলেছে যে headকোনও দৈর্ঘ্যের রেখাগুলি সমর্থন করা উচিত (সীমাবদ্ধ নয় LINE_MAX)

সাথে zsh:

IFS= read -rk988 -u0 var < input &&
print -rn -- $var > output

বা:

var=$(head -c 988 < input && echo .) && var=${var%.}
print -rn -- $var > output

এমনকি এর মধ্যে zshযদি NUL $varবাইট থাকে, আপনি zshবিল্টিনগুলি ( printউপরের মতো ) বা ফাংশনগুলির পক্ষে এটি আর্গুমেন্ট হিসাবে পাস করতে পারেন , তবে এক্সিকিউটেবলের পক্ষে আর্গুমেন্ট হিসাবে নন, এক্সিকিউটেবলের কাছে আর্গুমেন্টগুলি NUL সীমানাযুক্ত স্ট্রিং, এটি শেলের চেয়ে আলাদা কার্নেলের সীমাবদ্ধতা।


zshএকমাত্র শেল নয় যা শেল ভেরিয়েবলে এক বা একাধিক NUL বাইট সংরক্ষণ করতে পারে। ksh93এটাও করতে পারে। অভ্যন্তরীণভাবে, ksh93কেবল বেস 64-এনকোড স্ট্রিং হিসাবে বাইনারি ভেরিয়েবল সংরক্ষণ করে।
এফএমপুরফি

@ fpmurphy1, এটি আমি বাইনারি ডেটা হ্যান্ডলিং বলি না , ভেরিয়েবলটিতে বাইনারি ডেটা থাকে না, উদাহরণস্বরূপ আপনি তাদের উপর কোনও শেল অপারেটর ব্যবহার করতে পারবেন না, আপনি এটির বিল্টিন বা ফাংশনগুলিতে তাদের পাস করতে পারবেন না ডিকোডেড ফর্ম ... আমি এটিকে বরং বিল্টইন বেস 64 বলেই ডাকে / ডিকোডিং সমর্থন করব
স্টাফেন চেজেলাস

11

আমি উচ্চাভিলাষী কারণে অগণিত কারণে একটি সি ++ কোডটিকে ব্যাশে অনুবাদ করার চেষ্টা করছি।

হ্যাঁ ঠিক. তবে এটি না করার জন্য আপনার খুব গুরুত্বপূর্ণ কারণটি বিবেচনা করা উচিত। মূলত, "বাশ" / "শ" / "সিএসএস" / "কেএসএইচ" এবং এর মতো বাইনারি ডেটা প্রক্রিয়াকরণের জন্য ডিজাইন করা হয়নি এবং মানক ইউনিক্স / লিনাক্স ইউটিলিটিগুলির বেশিরভাগই নয়।

আপনি সি ++ এর সাথে লেগে থাকা, বা পাইথন, রুবি বা পার্লের মতো স্ক্রিপ্টিং ভাষা ব্যবহার করতে পারেন যা বাইনারি ডেটা নিয়ে কাজ করতে সক্ষম।

ব্যাশে এটি করার আরও ভাল উপায় আছে কি?

বাশে এটি না করাই ভাল উপায়।


4
"বাশ এ না করাই ভাল উপায়" "
গুন্ট্রাম ব্লহম মনিকা

1
এই রুটে না যাওয়ার আরেকটি কারণ হ'ল ফলশ্রুতি প্রয়োগটি উল্লেখযোগ্যভাবে ধীর হয়ে চলবে এবং আরও সিস্টেম সংস্থান গ্রহণ করবে।
fpmurphy

বাশ পাইপলাইনগুলি উচ্চ-স্তরের ডোমেন সুনির্দিষ্ট ভাষা হিসাবে কাজ করতে পারে যা বোঝা বাড়াতে পারে increase একটি পাইপলাইন যে বাইনারি নয় সম্পর্কে কিছুই নেই, এবং কমান্ড লাইন টুলস হিসাবে প্রয়োগ করা বিভিন্ন ইউটিলিটি আছে বাইনারি ডেটা সাথে ইন্টারঅ্যাক্ট ( ffmpeg, imagemagick, dd)। এখন যদি কেউ একসাথে জিনিসগুলিকে আঠালো করে তোলার পরিবর্তে প্রোগ্রামিং করে থাকে তবে একটি সম্পূর্ণ চালিত প্রোগ্রামিং ভাষা ব্যবহার করার উপায়।
এট রিগ

6

আপনার প্রশ্ন থেকে:

শিরোনামের প্রথম 988 লাইন অনুলিপি করুন

আপনি যদি 988 লাইন অনুলিপি করছেন তবে এটি কোনও টেক্সট ফাইলের মতো বাইনারি নয় বলে মনে হচ্ছে। তবে, আপনার কোডটি 988 লাইন নয় 988 বাইট ধরেছে বলে মনে হচ্ছে, তাই আমি বাইটগুলি সঠিক বলে ধরে নেব।

hdr_988=`head -c 988 ${inputFile}`
echo -n "${hdr_988}" > ${output_hdr}

এই অংশটি কাজ নাও করতে পারে। একটি কিছুর জন্য, প্রবাহের যে কোনও NUL বাইট ছিটিয়ে দেওয়া হবে, কারণ আপনি ${hdr_988}কমান্ড লাইন যুক্তি হিসাবে ব্যবহার করেন এবং কমান্ড লাইন আর্গুমেন্টগুলিতে NUL থাকতে পারে না। ব্যাকটিকগুলি হোয়াইটস্পেস মুগিংও করতে পারে (আমি এটি সম্পর্কে নিশ্চিত নই)। (প্রকৃতপক্ষে, যেহেতু echoএকটি অন্তর্নির্মিত, তাই NUL- র নিষেধাজ্ঞাগুলি প্রয়োগ নাও হতে পারে, তবে আমি বলব এটি এখনও কার্যকর নয়))

কেন কেবল শেল ভেরিয়েবলের মাধ্যমে পাস না করে কেবল ইনপুট ফাইল থেকে আউটপুট ফাইলটিতে সরাসরি শিরোনামটি লিখবেন না?

head -c 988 "${inputFile}" >"${output_hdr}"

বা, আরও বহনযোগ্যভাবে,

dd if="${inputFile}" of="${output_hdr}" bs=988 count=1

যেহেতু আপনি উল্লেখ করেছেন যে আপনি bashপসিক্স শেলটি ব্যবহার করছেন না, তাই আপনার কাছে প্রক্রিয়া প্রতিস্থাপনের ব্যবস্থা রয়েছে, তবে এটি পরীক্ষা হিসাবে কীভাবে হবে?

cmp <(head -c 988 "${inputFile}") <(head -c 988 "${output_hdr}")

শেষ অবধি : ব্যাকটিকের পরিবর্তে ব্যবহার বিবেচনা করুন$( ... )


নোট করুন যে অ-নিয়মিত ফাইলগুলির ddজন্য সমতুল্য নয় headheadঅনেক করব read(2)প্রয়োজনীয় সিস্টেম কল ঐ 988 বাইট পেতে যখন ddমাত্র এক কি করতে হবে read(2)। গনুহ ddটি iflag=fullblockচেষ্টা করুন এবং পূর্ণ যে ব্লক পড়তে, কিন্তু যে তারপর কম পোর্টেবল head -c
স্টাফেন চেজেলাস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.