কীভাবে ফাইলকে সর্বোচ্চ সংখ্যক অক্ষরে (বাইট নয়) কেটে যাবে


13

প্রদত্ত সংখ্যক অক্ষরগুলিতে আমি কীভাবে একটি (ইউটিএফ -8 এনকোডযুক্ত) পাঠ্য ফাইলটি ছাঁটাই করতে পারি? আমি লাইনের দৈর্ঘ্যের বিষয়ে যত্নশীল না এবং কাটাটি শব্দের মাঝখানে হতে পারে।

  • cut লাইনে অপারেটিং বলে মনে হচ্ছে, তবে আমি একটি সম্পূর্ণ ফাইল চাই।
  • head -c বাইট ব্যবহার করে, অক্ষর নয়।

মনে রাখবেন যে GNU বাস্তবায়ন cutএখনও মাল্টি-বাইট অক্ষরকে সমর্থন করে না। যদি এটি হয়, আপনি করতে পারেন cut -zc-1234 | tr -d '\0'
স্টাফেন চেজেলাস

আপনি কীভাবে ইমোজিগুলি পরিচালনা করতে চান? কয়েকটি হল আরো একটি অক্ষর ... stackoverflow.com/questions/51502486/...
phuzi

2
একটি চরিত্র কি? কিছু প্রতীক কয়েকটি কোড পয়েন্ট ব্যবহার করে
জেসেন

উত্তর:


14

কিছু সিস্টেমে একটি truncateকমান্ড থাকে যা ফাইলগুলি কয়েকটি বাইট (অক্ষর নয়) থেকে কেটে দেয় ।

আমি এমন কয়েকটি চরিত্রের সংক্ষিপ্ত বিবরণ সম্পর্কে জানি না, যদিও আপনি perlবেশিরভাগ সিস্টেমে ডিফল্টরূপে ইনস্টল করা থাকতে পারেন:

Perl

perl -Mopen=locale -ne '
  BEGIN{$/ = \1234} truncate STDIN, tell STDIN; last' <> "$file"
  • এর সাহায্যে -Mopen=locale, আমরা অক্ষরগুলি কী কী তা লোকের ধারণাটি ব্যবহার করি (সুতরাং ইউটিএফ -8 চরসেট ব্যবহার করে লোকালগুলিতে, এটি ইউটিএফ -8 এনকোডেড অক্ষর)। -CSআপনি যদি লোকেলের চরসেট নির্বিশেষে ইউটিএফ -8 এ আই / ওকে ডিকডড / এনকোড করতে চান তবে এর সাথে প্রতিস্থাপন করুন ।

  • $/ = \1234: আমরা একটি পূর্ণসংখ্যা যা সংশোধন করা হয়েছে দৈর্ঘ্য রেকর্ড নির্দিষ্ট করার (সংখ্যা একটি উপায় একটি রেফারেন্স রেকর্ড বিভাজক সেট অক্ষর )।

  • তারপরে প্রথম রেকর্ডটি পড়ার পরে, আমরা স্টিডিনকে জায়গায় কাটা (সুতরাং প্রথম রেকর্ডের শেষে) এবং প্রস্থান করি।

জিএনইউ সেড

জিএনইউ দিয়ে sedআপনি এটি করতে পারলেন (ধরে নিলেন যে ফাইলটিতে NUL টি অক্ষর বা বাইটের ক্রম নেই যা বৈধ অক্ষর তৈরি করে না - উভয়ই পাঠ্য ফাইলের ক্ষেত্রে সত্য হওয়া উচিত):

sed -Ez -i -- 's/^(.{1234}).*/\1/' "$file"

তবে এটি অনেক কম দক্ষ, কারণ এটি ফাইলটি পুরোপুরি পড়ে এবং এটি পুরো স্মৃতিতে সঞ্চয় করে এবং একটি নতুন অনুলিপি লেখেন।

জিএনইউ অবাক

জিএনইউর সাথে একই awk:

awk -i inplace -v RS='^$' -e '{printf "%s", substr($0, 1, 1234)}' -E /dev/null "$file"
  • -e code -E /dev/null "$file" যথেচ্ছ ফাইলের নামটি পাস করার এক উপায় one gawk
  • RS='^$': স্লুর্প মোড

শেল বিল্টিনস

সঙ্গে ksh93, bashবা zsh(ব্যতীত অন্য শেল সঙ্গে zsh, বিষয়বস্তু NUL ধারণ করে না অভিমানী বাইট):

content=$(cat < "$file" && echo .) &&
  content=${content%.} &&
  printf %s "${content:0:1234}" > "$file"

সহ zsh:

read -k1234 -u0 s < $file &&
  printf %s $s > $file

বা:

zmodload zsh/mapfile
mapfile[$file]=${mapfile[$file][1,1234]}

এর সাথে ( ksh93বা এর বেশ কয়েকটি সংস্করণে বহু-বাইট অক্ষরের জন্য এটি বোগাসbash সাবধান ):bash

IFS= read -rN1234 s < "$file" &&
  printf %s "$s" > "$file"

ksh93এটির <>;পুনঃনির্দেশ অপারেটরের মাধ্যমে পুনরায় লেখার পরিবর্তে ফাইলটি জায়গায় ছাঁটাই করতে পারে :

IFS= read -rN1234 0<>; "$file"

আইকনভি + মাথা

করার প্রিন্ট প্রথম 1234 অক্ষর, অন্য কোনো বিকল্প মত চরিত্র প্রতি বাইটের একটি নির্দিষ্ট সংখ্যা দিয়ে এনকোডিং রূপান্তর হতে পারে UTF32BE/ UCS-4:

iconv -t UCS-4 < "$file" | head -c "$((1234 * 4))" | iconv -f UCS-4

head -cমানক নয়, তবে মোটামুটি সাধারণ। একটি স্ট্যান্ডার্ড সমতুল্য হবে dd bs=1 count="$((1234 * 4))"তবে কম দক্ষ হবে, কারণ এটি ইনপুট পড়বে এবং আউটপুট এক সময়ে লিখবে write iconvএকটি স্ট্যান্ডার্ড কমান্ড তবে এনকোডিংয়ের নামগুলি প্রমিত করা হয় না, সুতরাং আপনি সিস্টেমগুলি ছাড়াই খুঁজে পেতে পারেনUCS-4

মন্তব্য

যাইহোক, আউটপুটে সর্বাধিক 1234 অক্ষর থাকলেও এটি বৈধ পাঠ্য না হয়ে শেষ হতে পারে, কারণ এটি সম্ভবত একটি সীমানা ছাড়ানো লাইনে শেষ হবে।

আরও মনে রাখবেন যে যখন এই সমাধানগুলি কোনও চরিত্রের মাঝখানে পাঠ্য কেটে না দেয় তবে তারা এটি গ্রাফিমের মাঝখানে ভেঙে ফেলতে পারে , éযেমন ইউ + 0065 ইউ + 0301 হিসাবে প্রকাশিত হয়েছিল (এর eপরে সংশ্লেষিত তীব্র উচ্চারণটি হবে), বা তাদের ক্ষয় ফর্মগুলিতে হাঙ্গুলের সিলেবল গ্রাফিগুলি।


Pipe এবং পাইপ ইনপুটটিতে আপনি জিএনইউ এক্সটেনশনটি bsব্যবহার না করে নির্ভরযোগ্যতার সাথে 1 টির চেয়ে অন্য মানগুলি ব্যবহার করতে পারবেন না , পাইপটি পূরণ করার চেয়ে দ্রুত পড়লে তা সংক্ষিপ্ত পড়তে পারেiflag=fullblockddiconv


করতে পারেdd bs=1234 count=4
জেসেন 11

2
@ জেসেন, এটি নির্ভরযোগ্য হবে না। সম্পাদনা দেখুন।
স্টাফেন চেজেলাস

কি দারুন! আপনি কাছাকাছি রাখা সহজ হবে! আমি ভেবেছিলাম যে আমি অনেক সহজ ইউনিক্স কমান্ড জানি কিন্তু এটি দুর্দান্ত বিকল্পগুলির একটি অবিশ্বাস্য তালিকা।
মার্ক স্টিয়ার্ট

5

আপনি যদি জানেন যে টেক্সট ফাইলটিতে ইউনিকোডটি ইউটিএফ -8 হিসাবে এনকোডযুক্ত রয়েছে তবে ইউনিকোড অক্ষর সত্তার ক্রম পেতে আপনাকে প্রথমে ইউটিএফ -8 ডিকোড করতে হবে এবং সেগুলি বিভক্ত করতে হবে।

আমি কাজের জন্য পাইথন ৩.x বেছে নেব।

পাইথন ফাংশন 3.x সঙ্গে (ওপেন) একটি অতিরিক্ত চাবি শব্দ যুক্তি আছে encoding=পড়ার জন্য টেক্সট ফাইলIo.TextIOBase.read () পদ্ধতির বিবরণ আশাব্যঞ্জক বলে মনে হচ্ছে।

পাইথন 3 ব্যবহার করে এটি দেখতে এরকম হবে:

truncated = open('/path/to/file.txt', 'rt', encoding='utf-8').read(1000)

স্পষ্টতই একটি আসল সরঞ্জাম কমান্ড-লাইন আর্গুমেন্ট, ত্রুটি পরিচালনা ইত্যাদি add

পাইথন ২.x এর সাহায্যে আপনি নিজের ফাইল-জাতীয় অবজেক্টটি প্রয়োগ করতে পারেন এবং ইনপুট ফাইলটি লাইন-বাই-লাইনে ডিকোড করতে পারেন।


হ্যাঁ, আমি এটা করতে পারতাম। তবে এটি সিআই বিল্ড মেশিনগুলির জন্য, সুতরাং আমি কিছু স্ট্যান্ডার্ড লিনাক্স কমান্ড ব্যবহার করতে চাই।
পিটেল

5
আপনার লিনাক্সের স্বাদে "স্ট্যান্ডার্ড লিনাক্স" যাই হোক না কেন ...
মাইকেল স্ট্রাইডার

1
আসলে, পাইথন, যাইহোক এটির কিছু সংস্করণ, আজকাল এটি বেশ মানসম্পন্ন।
মারু

আমি ইতিমধ্যে পাইথন 3 এর স্নিপেট দিয়ে আমার উত্তর সম্পাদনা করেছি যা স্পষ্টভাবে পাঠ্য-ফাইলগুলি প্রক্রিয়া করতে পারে।
মাইকেল স্ট্রাইডার

0

আমি অন্য পদ্ধতি যুক্ত করতে চাই সম্ভবত সেরা পারফরম্যান্স বুদ্ধিমান, এবং অনেক বেশি দীর্ঘ নয়, তবে বুঝতে সহজ:

#!/bin/bash

chars="$1"
ifile="$2"
result=$(cat "$ifile")
rcount=$(echo -n "$result" | wc -m)

while [ $rcount -ne $chars ]; do
        result=${result::-1}
        rcount=$(echo -n "$result" | wc -m)
done

echo "$result"

সাথে এটি চাওয়া $ ./scriptname <desired chars> <input file>

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


হ্যাঁ, এটি অবশ্যই পারফরম্যান্সের জন্য ভয়াবহ। একটি দৈর্ঘ্যের এন wcফাইলের জন্য, ফাইলের অর্ধেক পথের জন্য অর্ধেক পথের জন্য অর্ধেক হে (এন total 2) এর অর্ডার ধরে গণনা করা হয়। আপনার বৃদ্ধি বা হ্রাস, যেমন echo -n "${result::-$chop}" | wc -mবা অন্য কিছু ব্যবহার করে রৈখিক অনুসন্ধানের পরিবর্তে বাইনারি-অনুসন্ধান করা উচিত। (এবং আপনি যখন এটির সাথে থাকবেন তখন ফাইল সামগ্রীগুলি -eবা অন্য কোনও কিছু দিয়ে, সম্ভবত ব্যবহার করা শুরু হলেও এটি নিরাপদ করুন printf)। তবে আপনি এখনও এমন পদ্ধতিগুলিকে মারবেন না যা কেবলমাত্র প্রতিটি ইনপুট চরিত্র একবারে দেখে, তাই সম্ভবত এটির পক্ষে উপযুক্ত নয়।
পিটার কর্ডেস

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

1
আপনি $desired_charsনিম্ন প্রান্তে বা সম্ভবত 4*$desired_charsউচ্চ প্রান্তে বাইট দিয়ে শুরু করে সঠিক জায়গার কাছাকাছি যেতে পারেন । তবে এখনও আমি অন্য কিছু সম্পূর্ণরূপে ব্যবহার করা ভাল বলে মনে করি।
পিটার কর্ডস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.