লাইনে ফাইল কেটে যাবে কীভাবে?


13

আমার কাছে প্রচুর ফাইল রয়েছে, যার কয়েকটি খুব দীর্ঘ। ফাইলের শেষটি সরিয়ে তারা যদি বড় হয় তবে আমি তাদের একটি নির্দিষ্ট আকারে ছাঁটাতে চাই। তবে আমি কেবল পুরো লাইনগুলি সরাতে চাই। কিভাবে আমি এটি করতে পারব? এটি লিনাক্স টুলচেইন দ্বারা পরিচালিত এমন ধরণের জিনিসটির মতো মনে হয় তবে আমি সঠিক কমান্ডটি জানি না।

উদাহরণস্বরূপ, বলুন আমার কাছে 300,000 বাইট লাইন সহ একটি 120,000 বাইট ফাইল রয়েছে এবং আমি এটি 10,000 বাইটে ছাঁটাই করার চেষ্টা করছি। প্রথম 33 টি লাইন থাকা উচিত (9900 বাইট) এবং বাকীটি কাটা উচিত। আমি 10,000 বাইটে হুবহু কাটতে চাই না, যেহেতু এটি একটি আংশিক রেখা ছাড়বে।

অবশ্যই ফাইলগুলি পৃথক দৈর্ঘ্যের এবং লাইনগুলি একই দৈর্ঘ্যের নয় not

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


আমার উত্তরটি মুছে ফেলা হয়েছে ... আমার ধারণা বাইটসের ফাইল আকারের জিনিসটি খুব পরিষ্কার ছিল না, দুঃখিত। হতে পারে আপনি আপনার প্রশ্নটি সম্পাদনা করতে এবং সেই অংশটি স্পষ্ট করতে পারেন (উদাহরণস্বরূপ একটি উদাহরণ সহ)?
স্ল্যাক করুন

@ এসএলএইচএইচকি: আমি অস্পষ্ট ছিলাম বলেই আপনার প্রতিনিধিত্ব হারাতে দেখে দুঃখিত! ... আমি এটি ঠিক করতে পারি কিনা তা আমাকে দেখতে দিন।
চার্লস

কোন উদ্বেগ, আমি শুধু জিজ্ঞাসা করা উচিত ছিল, দুঃখিত :)
slhck

উত্তর:


1

sed/ wcজটিলতা পূর্ববর্তী উত্তর এড়ানো যায় যদি awkব্যবহার করা হয়। ওপি থেকে প্রদত্ত উদাহরণ ব্যবহার করে ( 10000 বাইটের পূর্বে সম্পূর্ণ লাইনগুলি দেখানো হচ্ছে ):

awk '{i += (length() + 1); if (i <= 10000) print $ALL}' myfile.txt

10000 ম বাইট সমেত সম্পূর্ণ লাইনটিও দেখানো হচ্ছে যদি সেই বাইটটি লাইনের শেষে না থাকে:

awk '{i += (length() + 1); print $ALL; if (i >= 10000) exit}' myfile.txt

উপরের উত্তরটি ধরে নেওয়া হয়েছে:

  1. পাঠ্য ফাইলটি ইউনিক্স লাইন টার্মিনেটর ( \n)। ডস / উইন্ডোজ পাঠ্য ফাইলগুলির জন্য ( \r\n), পরিবর্তন করুনlength() + 1 করুনlength() + 2
  2. পাঠ্য ফাইলটিতে কেবল একক বাইট অক্ষর রয়েছে। যদি মাল্টিবাইট চরিত্র থাকে (যেমন ইউনিকোড পরিবেশের অধীনে), LC_CTYPE=Cবাইট স্তরটিতে ব্যাখ্যার জন্য জোর করতে পরিবেশ সেট করুন।

15

দ্য sedপদ্ধতির জরিমানা, কিন্তু লাইনের উপর লুপ নয়। আপনি যদি জানেন যে আপনি কতগুলি লাইন রাখতে চান (উদাহরণস্বরূপ, আমি এখানে 99 ব্যবহার করি), আপনি এটি এটি করতে পারেন:

sed -i '100,$ d' myfile.txt

ব্যাখ্যা: sed একটি নিয়মিত এক্সপ্রেশন প্রসেসর। -iপ্রদত্ত বিকল্পের সাহায্যে এটি সরাসরি একটি ফাইল প্রক্রিয়া করে ("ইনলাইন") - কেবল এটি পড়ার পরিবর্তে এবং ফলাফলকে স্ট্যান্ডার্ড আউটপুটে লেখার পরিবর্তে। 100,$এর অর্থ "ফাইলের শেষে 100 লাইন থেকে" - এবং কমান্ডটি অনুসরণ করা হয় d, যা আপনি সম্ভবত "মুছুন" এর পক্ষে দাঁড়াতে সঠিকভাবে অনুমান করেছিলেন। সুতরাং সংক্ষেপে, কমান্ডটির অর্থ: "myfile.txt থেকে ফাইলের 100 লাইন থেকে সমস্ত লাইন মুছুন"। আপনি 99 লাইন রাখতে চাইলে 100 টি মুছে ফেলা প্রথম লাইন।

সম্পাদনা: পারেন, অন্য দিকে, সেখানে লগ ফাইল যেখানে আপনি যেমন রাখার বিষয়ে নিশ্চিত গত 100 লাইন:

[ $(wc -l myfile.txt) -gt 100 ] && sed -i "1,$(($(wc -l myfile.txt|awk '{print $1}') - 100)) d" myfile.txt

এখানে কি হচ্ছে:

  • [ $(wc -l myfile.txt) -gt 100 ]: ফাইলটিতে 100 টিরও বেশি লাইন থাকলে কেবল নিম্নলিখিতটি করুন
  • $((100 - $(wc -l myfile.txt|awk '{print $1}'))): মুছে ফেলতে লাইনের সংখ্যা গণনা করুন (অর্থাত্ ফাইলের সমস্ত রেখাগুলি (শেষ) 100 বাদে রাখতে হবে)
  • 1, $((..)) d: প্রথম থেকে গণনা করা লাইনের সমস্ত লাইন সরান

সম্পাদনা: যেহেতু আরও বিশদ দেওয়ার জন্য প্রশ্নটি কেবল সম্পাদিত হয়েছিল, আমি আমার উত্তরের সাথে এই অতিরিক্ত তথ্যও অন্তর্ভুক্ত করব। যুক্ত তথ্যগুলি হ'ল:

  • একটি নির্দিষ্ট আকার ফাইলের সাথে থাকবে (10,000 বাইট)
  • প্রতিটি লাইনের বাইটগুলিতে একটি নির্দিষ্ট আকার থাকে (উদাহরণস্বরূপ 300 বাইট)

এই ডেটা থেকে "/" হিসাবে থাকা লাইনের সংখ্যা গণনা করা সম্ভব, উদাহরণস্বরূপ 33 টি লাইন বোঝানো হবে। গণনার জন্য শেল শব্দ: $((size_to_remain / linesize))(কমপক্ষে ব্যাশ ব্যবহার করে লিনাক্সে, ফলাফলটি পূর্ণসংখ্যা হয়)। সমন্বিত কমান্ড এখন পড়তে হবে:

# keep the start of the file (OPs question)
sed -i '34,$ d' myfile.txt
# keep the end of the file (my second example)
[ $(wc -l myfile.txt) -gt 33 ] && sed -i "1,33 d" myfile.txt

আকারগুলি আগাম হিসাবে পরিচিত হিসাবে, আর এম্বেড করা কোনও গণনার প্রয়োজন নেই sed কমান্ডের । তবে নমনীয়তার জন্য কিছু শেল স্ক্রিপ্টের ভিতরে কেউ ভেরিয়েবল ব্যবহার করতে পারে।

ফাইলের আকারের উপর ভিত্তি করে শর্তসাপেক্ষ প্রক্রিয়াজাতকরণের জন্য, কেউ "নীচে" পরীক্ষা-কনস্ট্রাক্ট ব্যবহার করতে পারেন:

[ "$(ls -lk $file | awk ' {print $5}')" -gt 100 ] &&

যার অর্থ: "যদি আকারটি 100 $fileকেবি ছাড়িয়ে যায় তবে কর ..." (কেবিতে ls -lkফাইলের আকারের অবস্থান 5 অবস্থানে রয়েছে, সুতরাং awkএটি সঠিকভাবে বের করার জন্য ব্যবহৃত হয়)।


ওপি একটি নির্দিষ্ট বাইট আকারের উপর ভিত্তি করে ফাইলটি কাটতে চায় - কেবল লাইনের ক্ষেত্রে দৈর্ঘ্য নয়। আমি জড়িত আমার উত্তর মোছা head -n
স্ল্যাক করুন

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

না - আকারগুলি আগে থেকে জানা যায় না। এটি একটি উদাহরণ ছিল। প্রতিটি ফাইলের আকার আলাদা হবে এবং লাইনগুলি অনিয়মিত দৈর্ঘ্যের of কিছু ফাইল একেবারে কাটা দরকার হয় না।
চার্লস

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

আমি বর্তমানে যা করতে পারি তার মধ্যে প্রথমত এন লাইনগুলি পাওয়া, তাদের উপর ভিত্তি করে গড় দৈর্ঘ্য গণনা করা এবং এই মানটি ব্যবহার করা উচিত। এটা কি আপনাকে সাহায্য করবে?
ইজজি

0

এটি করার জন্য কোনও আদেশ সন্ধান করতে ব্যর্থ হয়ে আমি একটি দ্রুত স্ক্রিপ্ট লিখেছি (পরীক্ষা করা হয়নি):

#!/bin/sh

# Usage: $0 glob.* 25000
# where glob.* is a wildcard pattern and 25000 is the maximum number of bytes.

limit=20000
tmp=/tmp/trim
[[ "$2" == +([0-9]) ]] || limit=$2
limit=`expr $len + 1`
for file in $1;
do
    [[ `wc -c $file` -lt $limit ]] && continue
    head -c $file > $tmp
    sed '$d' $tmp
    $tmp > $file
done

-1

আপনি ফাইল থেকে লাইন অপসারণ করতে লিনাক্স কমান্ড সেড ব্যবহার করতে পারেন। নিম্নলিখিত কমান্ড ফাইলনাম.টেক্সটের শেষ লাইনটি মুছুন:

sed '$d' filename.txt

অ্যাজকে বা সন্ধানের সাহায্যে আপনি আপনার সেড কমান্ডের সাথে মেলে এমন প্যাটার্ন অনুসন্ধান করতে পারেন। প্রথমে আপনি awk দিয়ে অনুসন্ধান করুন বা যে ফাইলগুলি সংক্ষিপ্ত করতে চান তার সন্ধান করুন এবং তারপরে আপনি সেড দিয়ে লাইনগুলি সরিয়ে ফেলতে পারেন।


-1

আমি লেজের সাথে একই রকম কিছু করেছি। এক্ষেত্রে শুধুমাত্র শেষ 10,000 টি লাইন রাখার জন্য:

TMP=$(tail -n 10000 /path/to/some/file 2>/dev/null) && echo "${TMP}" > /path/to/some/file
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.