আমার কাছে খুব বড় ফাইল রয়েছে (GB 400 গিগাবাইট) এবং এখান থেকে আমার শেষ দুটি লাইন সরিয়ে ফেলতে হবে। আমি ব্যবহার করার চেষ্টা করেছি sed
, তবে আমি হাল ছাড়ার আগে কয়েক ঘন্টা ধরে এটি চলেছিল। এটি করার কোনও দ্রুত উপায় আছে, বা আমি আটকে আছি sed
?
আমার কাছে খুব বড় ফাইল রয়েছে (GB 400 গিগাবাইট) এবং এখান থেকে আমার শেষ দুটি লাইন সরিয়ে ফেলতে হবে। আমি ব্যবহার করার চেষ্টা করেছি sed
, তবে আমি হাল ছাড়ার আগে কয়েক ঘন্টা ধরে এটি চলেছিল। এটি করার কোনও দ্রুত উপায় আছে, বা আমি আটকে আছি sed
?
উত্তর:
এটি কত দ্রুত হয় তা দেখার জন্য আমি কোনও বড় ফাইলে এটি চেষ্টা করি নি, তবে এটি মোটামুটি দ্রুত হওয়া উচিত।
কোনও ফাইলের শেষে থেকে লাইনগুলি সরাতে স্ক্রিপ্টটি ব্যবহার করতে:
./shorten.py 2 large_file.txt
এটি ফাইলের শেষের দিকে অনুসন্ধান করে, শেষ অক্ষরটি একটি নতুন লাইন কিনা তা যাচাই করে তা পরীক্ষা করে, তারপরে প্রতিটি চরিত্রকে একবারে পিছনে যেতে পারা যায় যতক্ষণ না এটি তিনটি নতুন লাইন খুঁজে পাওয়া যায় এবং ঠিক সেই বিন্দুটির পরে ফাইলটি কেটে যায়। পরিবর্তন জায়গায় করা হয়।
সম্পাদনা: আমি নীচে একটি পাইথন ২.৪ সংস্করণ যুক্ত করেছি।
পাইথন 2.5 / 2.6 এর জন্য এখানে একটি সংস্করণ রয়েছে:
#!/usr/bin/env python2.5
from __future__ import with_statement
# also tested with Python 2.6
import os, sys
if len(sys.argv) != 3:
print sys.argv[0] + ": Invalid number of arguments."
print "Usage: " + sys.argv[0] + " linecount filename"
print "to remove linecount lines from the end of the file"
exit(2)
number = int(sys.argv[1])
file = sys.argv[2]
count = 0
with open(file,'r+b') as f:
f.seek(0, os.SEEK_END)
end = f.tell()
while f.tell() > 0:
f.seek(-1, os.SEEK_CUR)
char = f.read(1)
if char != '\n' and f.tell() == end:
print "No change: file does not end with a newline"
exit(1)
if char == '\n':
count += 1
if count == number + 1:
f.truncate()
print "Removed " + str(number) + " lines from end of file"
exit(0)
f.seek(-1, os.SEEK_CUR)
if count < number + 1:
print "No change: requested removal would leave empty file"
exit(3)
এখানে পাইথন 3 সংস্করণ রয়েছে:
#!/usr/bin/env python3.0
import os, sys
if len(sys.argv) != 3:
print(sys.argv[0] + ": Invalid number of arguments.")
print ("Usage: " + sys.argv[0] + " linecount filename")
print ("to remove linecount lines from the end of the file")
exit(2)
number = int(sys.argv[1])
file = sys.argv[2]
count = 0
with open(file,'r+b', buffering=0) as f:
f.seek(0, os.SEEK_END)
end = f.tell()
while f.tell() > 0:
f.seek(-1, os.SEEK_CUR)
print(f.tell())
char = f.read(1)
if char != b'\n' and f.tell() == end:
print ("No change: file does not end with a newline")
exit(1)
if char == b'\n':
count += 1
if count == number + 1:
f.truncate()
print ("Removed " + str(number) + " lines from end of file")
exit(0)
f.seek(-1, os.SEEK_CUR)
if count < number + 1:
print("No change: requested removal would leave empty file")
exit(3)
এখানে পাইথন ২.৪ সংস্করণ রয়েছে:
#!/usr/bin/env python2.4
import sys
if len(sys.argv) != 3:
print sys.argv[0] + ": Invalid number of arguments."
print "Usage: " + sys.argv[0] + " linecount filename"
print "to remove linecount lines from the end of the file"
sys.exit(2)
number = int(sys.argv[1])
file = sys.argv[2]
count = 0
SEEK_CUR = 1
SEEK_END = 2
f = open(file,'r+b')
f.seek(0, SEEK_END)
end = f.tell()
while f.tell() > 0:
f.seek(-1, SEEK_CUR)
char = f.read(1)
if char != '\n' and f.tell() == end:
print "No change: file does not end with a newline"
f.close()
sys.exit(1)
if char == '\n':
count += 1
if count == number + 1:
f.truncate()
print "Removed " + str(number) + " lines from end of file"
f.close()
sys.exit(0)
f.seek(-1, SEEK_CUR)
if count < number + 1:
print "No change: requested removal would leave empty file"
f.close()
sys.exit(3)
আপনি GNU মাথা চেষ্টা করতে পারেন
head -n -2 file
head: illegal line count -- -2
আমি দেখতে পাচ্ছি আমার ডেবিয়ান স্কুইজ / টেস্টিং সিস্টেমগুলি (তবে লেনি / স্থিতিশীল নয়) "কোরুটিলস" প্যাকেজের অংশ হিসাবে একটি "কাটা" কমান্ড অন্তর্ভুক্ত রয়েছে।
এটি দিয়ে আপনি সাধারণভাবে কিছু করতে পারেন
truncate --size=-160 myfile
ফাইলটির শেষে থেকে 160 বাইট অপসারণ করতে (স্পষ্টত আপনার কতগুলি অক্ষর অপসারণ করতে হবে তা সঠিকভাবে নির্ধারণ করতে হবে)।
dd
স্ক্রিপ্ট এটি করবে (ফে লাস্ট কিলোবাইট পেতে তার জন্য ইনপুট অফসেট নির্দিষ্ট করতে হবে এবং তারপরে ব্যবহার করতে হবে tail -2 | LANG= wc -c
, বা এর মতো স্ট্যাথ))
tail
বড় ফাইলগুলির পক্ষেও কার্যকর, - tail | wc -c
ছাঁটাই করার জন্য বাইটের সংখ্যা গণনা করতে ব্যবহার করতে পারেন ।
সেডের সমস্যাটি হ'ল এটি একটি স্ট্রিম এডিটর - এটি যদি আপনি কেবলমাত্র শেষের দিকে পরিবর্তন করতে চান তবে এটি পুরো ফাইলটি প্রক্রিয়া করবে। সুতরাং যাই হোক না কেন, আপনি লাইন লাইন একটি নতুন 400GB ফাইল তৈরি করছেন। যে কোনও সম্পাদক যা পুরো ফাইলটিতে পরিচালনা করে তাদের সম্ভবত এই সমস্যাটি হবে।
আপনি যদি লাইনের সংখ্যা জানেন তবে আপনি ব্যবহার করতে পারেন head
তবে এটি আবার বিদ্যমান ফাইলটি পরিবর্তে পরিবর্তে একটি নতুন ফাইল তৈরি করে। আমার ধারণা, আপনি ক্রিয়াটির সরলতা থেকে গতি অর্জন করতে পারেন।
আপনি পারে ব্যবহার করে আরো ভালভাবে ভাগ্য আছে split
সম্পাদনা গত এক, এবং তারপর ব্যবহার করে, ছোট টুকরা মধ্যে ফাইল বিরতি cat
আবার একত্রিত করতে, কিন্তু আমি নিশ্চিত যদি এটা কোন ভাল হবে না। আমি লাইনগুলির চেয়ে বাইট গণনাগুলি ব্যবহার করব, অন্যথায় এটি সম্ভবত দ্রুততর হবে না - আপনি এখনও একটি নতুন 400 জিবি ফাইল তৈরি করতে যাচ্ছেন।
ভিআইএম চেষ্টা করুন ... আমি নিশ্চিত নই যে এটি কৌশলটি করবে কিনা, কারণ আমি এটি এত বড় ফাইলটিতে কখনও ব্যবহার করি নি, তবে অতীতে ছোট বড় ফাইলগুলিতে এটি ব্যবহার করেছি।
কোন ধরণের ফাইল এবং কোন ফর্ম্যাটে? পার্ল নির্ভর কোন ধরণের ফাইলের উপর নির্ভরশীল - টেক্সট, গ্রাফিক্স, বাইনারি? এটি কীভাবে ফর্ম্যাট করা হয় - সিএসভি, টিএসভি ...
আপনি যদি বাইটটিতে ফাইলের আকার জানেন (400000000160 বলুন) এবং আপনি জানেন যে শেষ দুটি লাইনের ফালা ফেলার জন্য আপনাকে ঠিক 160 টি অক্ষর অপসারণ করতে হবে, তবে এর মতো কিছু
dd if=originalfile of=truncatedfile ibs=1 count=400000000000
কৌতুক করা উচিত। আমি যুগে যুগে ক্রুদ্ধ হয়ে ডিডি ব্যবহার করেছি; আমার মনে হচ্ছে আপনি যদি আরও বড় আকারের ব্লক আকার ব্যবহার করেন তবে জিনিসগুলি দ্রুত গতিতে চলেছে তবে আপনি এটি করতে পারেন কিনা তা নির্ভর করে আপনি যে লাইনগুলি ফেলে দিতে চান তা কোনও একাধিকতে রয়েছে কিনা depends
একটি নির্দিষ্ট আকারে পাঠ্য রেকর্ডগুলি প্যাড করার জন্য ডিডির আরও কিছু বিকল্প রয়েছে যা প্রাথমিক পাস হিসাবে কার্যকর হতে পারে।
যদি "ট্রাঙ্কেট" কমান্ডটি আপনার সিস্টেমে উপলব্ধ না হয় (আমার অন্য উত্তরটি দেখুন), একটি নির্দিষ্ট দৈর্ঘ্যে কোনও ফাইলকে কাটাতে সিস্টেম কল করার জন্য "ম্যান 2 ট্রুঙ্কেট" দেখুন।
স্পষ্টতই আপনাকে জানতে হবে যে আপনাকে ফাইলটি কেটে ফেলতে হবে (অক্ষরের দৈর্ঘ্যের দুটি লাইনের দৈর্ঘ্য; কোনও সিআর / এলএফ অক্ষর গণনা করতে ভুলবেন না) you
এটি চেষ্টা করার আগে ফাইলটির একটি ব্যাকআপ তৈরি করুন!
আপনি যদি ইউনিক্স-স্টাইলের সমাধানগুলি পছন্দ করেন তবে আপনার কাছে তিনটি লাইন কোড (ম্যাক এবং লিনাক্সে পরীক্ষিত) ব্যবহার করে সংরক্ষণ এবং ইন্টারেক্টিভ লাইন কাটা থাকতে পারে।
ছোট + নিরাপদ ইউনিক্স-স্টাইলের লাইন কাটা (নিশ্চিতকরণের জন্য জিজ্ঞাসা করে):
n=2; file=test.csv; tail -n $n $file &&
read -p "truncate? (y/N)" -n1 key && [ "$key" == "y" ] &&
perl -e "truncate('$file', `wc -c <$file` - `tail -n $n $file | wc -c` )"
এই সমাধানটি কয়েকটি সাধারণ ইউনিক্স-সরঞ্জামগুলির উপর নির্ভর করে, তবে এখনও এর perl -e "truncate(file,length)"
নিকটতম প্রতিস্থাপন হিসাবে ব্যবহার করে truncate(1)
, যা সমস্ত সিস্টেমে উপলব্ধ নয়।
আপনি নিম্নলিখিত বিস্তৃত পুনরায় ব্যবহারযোগ্য শেল প্রোগ্রামটিও ব্যবহার করতে পারেন, যা একটি ব্যবহারের তথ্য সরবরাহ করে এবং কাটছাঁটি নিশ্চিতকরণ, বিকল্প বিশ্লেষণ এবং ত্রুটি পরিচালনার বৈশিষ্ট্যগুলি সরবরাহ করে।
বিস্তৃত লাইন কাটা স্ক্রিপ্ট :
#!/usr/bin/env bash
usage(){
cat <<-EOF
Usage: $0 [-n NUM] [-h] FILE
Options:
-n NUM number of lines to remove (default:1) from end of FILE
-h show this help
EOF
exit 1
}
num=1
for opt in $*; do case $opt in
-n) num=$2; shift;;
-h) usage; break;;
*) [ -f "$1" ] && file=$1; shift;;
esac done
[ -f "$file" ] || usage
bytes=`wc -c <$file`
size=`tail -n $num $file | wc -c`
echo "using perl 'truncate' to remove last $size of $bytes bytes:"
tail -n $num $file
read -p "truncate these lines? (y/N)" -n1 key && [ "$key" == "y" ] &&
perl -e "truncate('$file', $bytes - $size )"; echo ""
echo "new tail is:"; tail $file
এখানে ব্যবহারের উদাহরণ দেওয়া হল:
$ cat data/test.csv
1 nice data
2 cool data
3 just data
GARBAGE to be removed (incl. empty lines above and below)
$ ./rmtail.sh -n 3 data/test.csv
using perl 'truncate' to remove last 60 of 96 bytes:
GARBAGE to be removed (incl. empty lines above and below)
truncate these lines? (y/N)y
new tail is:
1 nice data
2 cool data
3 just data
$ cat data/test.csv
1 nice data
2 cool data
3 just data
#! / বিন / SH সম্পাদনা "$ 1" << এখানে $ ঘ ঘ W এখানে
পরিবর্তে জায়গায় করা হয়। এটি পাইথন স্ক্রিপ্টের চেয়ে সহজ এবং দক্ষ।
ed
আমার পাইথন স্ক্রিপ্টের চেয়ে 100 গুণ বেশি সময় লেগেছিল। আমি কেবলমাত্র কল্পনা করতে পারি যে OP০০০ গুণ বড় ওপি-র ফাইলের জন্য আরও কত পার্থক্য হবে।
অনুরূপ সমস্যা সমাধানের জন্য গৃহীত উত্তরটি পরিবর্তন করে। এন লাইনগুলি সরাতে সামান্য একটু টুইট করা যেতে পারে।
import os
def clean_up_last_line(file_path):
"""
cleanup last incomplete line from a file
helps with an unclean shutdown of a program that appends to a file
if \n is not the last character, remove the line
"""
with open(file_path, 'r+b') as f:
f.seek(0, os.SEEK_END)
while f.tell() > 0: ## current position is greater than zero
f.seek(-1, os.SEEK_CUR)
if f.read(1) == '\n':
f.truncate()
break
f.seek(-1, os.SEEK_CUR) ## don't quite understand why this has to be called again, but it doesn't work without it
এবং সম্পর্কিত পরীক্ষা:
import unittest
class CommonUtilsTest(unittest.TestCase):
def test_clean_up_last_line(self):
"""
remove the last incomplete line from a huge file
a line is incomplete if it does not end with a line feed
"""
file_path = '/tmp/test_remove_last_line.txt'
def compare_output(file_path, file_data, expected_output):
"""
run the same test on each input output pair
"""
with open(file_path, 'w') as f:
f.write(file_data)
utils.clean_up_last_line(file_path)
with open(file_path, 'r') as f:
file_data = f.read()
self.assertTrue(file_data == expected_output, file_data)
## test a multiline file
file_data = """1362358424445914,2013-03-03 16:53:44,34.5,151.16345879,b
1362358458954466,2013-03-03 16:54:18,34.5,3.0,b
1362358630923094,2013-03-03 16:57:10,34.5,50.0,b
136235"""
expected_output = """1362358424445914,2013-03-03 16:53:44,34.5,151.16345879,b
1362358458954466,2013-03-03 16:54:18,34.5,3.0,b
1362358630923094,2013-03-03 16:57:10,34.5,50.0,b
"""
compare_output(file_path, file_data, expected_output)
## test a file with no line break
file_data = u"""1362358424445914,2013-03-03 16:53:44,34.5,151.16345879,b"""
expected_output = "1362358424445914,2013-03-03 16:53:44,34.5,151.16345879,b"
compare_output(file_path, file_data, expected_output)
## test a file a leading line break
file_data = u"""\n1362358424445914,2013-03-03 16:53:44,34.5,151.16345879,b"""
expected_output = "\n"
compare_output(file_path, file_data, expected_output)
## test a file with one line break
file_data = u"""1362358424445914,2013-03-03 16:53:44,34.5,151.16345879,b\n"""
expected_output = """1362358424445914,2013-03-03 16:53:44,34.5,151.16345879,b\n"""
compare_output(file_path, file_data, expected_output)
os.remove(file_path)
if __name__ == '__main__':
unittest.main()
আপনি প্রাক্তন মোডে ভিম ব্যবহার করতে পারেন:
ex -sc '-,d|x' file
-,
শেষ 2 লাইন নির্বাচন করুন
d
মুছে ফেলা
x
সংরক্ষণ করেন এবং বন্ধ করেন
head -n -2 file