একটি লাইন-ভিত্তিক ফাইল পড়ুন যা কোনও নতুন লাইনের সাথে শেষ নাও হতে পারে


11

আমার কাছে এমন একটি ফাইল রয়েছে /tmp/urlFileযেখানে প্রতিটি লাইন একটি url উপস্থাপন করে। আমি ফাইলটি নিম্নরূপ থেকে পড়ার চেষ্টা করছি:

cat "/tmp/urlFile" | while read url
do
    echo $url
done

যদি শেষ লাইনটি কোনও নতুন লাইনের চরিত্রের সাথে শেষ না হয়, তবে সেই লাইনটি পড়বে না। আমি ভাবছিলাম কেন?

নতুন লাইন দিয়ে শেষ করা হয়েছে কি না, সমস্ত লাইন পড়া কি সম্ভব?



2
হাহ @ স্টাফেন আমি সেখানে টিবিডি পছন্দ করি ;-)।
স্টিফেন কিট

2
অনুপস্থিত থাকলে পেছনের নতুন লাইন যুক্ত করার আরও একটি উপায়; awk 1 /tmp/urlFile.. তাইawk 1 /tmp/urlFile | while ...
মুরু

@ মুরু, এটি এখানে অন্য যে কোনও চেয়ে ভাল উত্তর।
ওয়াইল্ডকার্ড

1
যেহেতু আপনি জিজ্ঞাসা করছেন কেন এটি পড়া হয় না: stackoverflow.com/a/729795/1968
কনরাড রুডল্ফ

উত্তর:


13

আপনি করতেন:

while IFS= read -r url || [ -n "$url" ]; do
  printf '%s\n' "$url"
done < url.list

(কার্যকরভাবে, সেই লুপটি সর্বশেষ (অ-) লাইনে হারিয়ে যাওয়া নিউলাইনটিকে আবার যুক্ত করে।

আরো দেখুন:


ধন্যবাদ। আমি লিঙ্কযুক্ত নিবন্ধগুলি পড়েছি এবং সম্ভবত আমি কিছু মিস করছি, কেন "সেই লুপটি সর্বশেষ (অ-) লাইনে হারিয়ে যাওয়া নিউলাইনটিকে আবার যুক্ত করে"?
টিম

1
@ টিম যা বলে স্টিফেনের মনে হচ্ছে এটি হ'ল এখানে যে সমস্ত printfকল রয়েছে সেহেতু এটি আউটপুটটিতে হারিয়ে যাওয়া নিউলাইনটিকে আবার যুক্ত করে \n
সের্গেই কলডিয়াজন্য

6

এটির সাথে অংশটি সমাধান হয়ে গেছে বলে মনে হচ্ছে readarray -t:

readarray -t urls "/tmp/urlFile"
for url in "${urls[@]}"; do
    printf '%s\n' "$url"
done

তবে নোট করুন যে এটি যুক্তিসঙ্গত আকারের ফাইলগুলির জন্য কাজ করে, এই সমাধানটি খুব বড় ফাইলগুলির সাথে একটি সম্ভাব্য নতুন সমস্যার পরিচয় দেয় - এটি প্রথমে ফাইলটিকে একটি অ্যারেতে পড়ে যা তারপরে অবশ্যই পুনরাবৃত্তি করা উচিত। খুব বড় ফাইলগুলির জন্য এটি সময় এবং মেমরি গ্রাসকারী উভয়ই হতে পারে, সম্ভাব্য ব্যর্থতার দিক থেকে।


ধন্যবাদ। এটি কোন অংশটি সমাধান করে এবং কোনটি তা করে না?
টিম

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

1
@ দোপঘোটি এটি ভাল তথ্য - আমি কি আপনাকে উত্তরটিতে সরাসরি যুক্ত করার পরামর্শ দিতে পারি?
আরজেহান্টার

থা উত্তর তাই সংশোধন করা হয়েছে।
ডোপঘোটি

5

দ্বারা সংজ্ঞা , একটি টেক্সট ফাইল লাইনের একটা ক্রম নিয়ে গঠিত। একটি রেখা একটি নিউলাইন চরিত্রের সাথে শেষ হয়। সুতরাং একটি পাঠ্য ফাইল একটি নতুন লাইন অক্ষর দিয়ে শেষ হয়, যদি না এটি খালি থাকে।

readবিল্টিন কেবল টেক্সট ফাইলগুলি পড়ার জন্য বোঝানো হয়। আপনি কোনও পাঠ্য ফাইলটি পাস করছেন না, সুতরাং আপনি এটি নির্বিঘ্নে কাজ করার আশা করতে পারবেন না। শেলটি সমস্ত লাইন পড়ে - এটি কী এড়িয়ে চলেছে তা শেষ লাইনের পরে অতিরিক্ত অক্ষর।

আপনার যদি কোনও সম্ভাব্য ত্রুটিযুক্ত ইনপুট ফাইল থাকে যা এটির শেষ লাইনটি অনুপস্থিত হতে পারে তবে আপনি এটিতে একটি নতুন লাইন যুক্ত করতে পারেন, নিশ্চিত হওয়া নিশ্চিত।

{ cat "/tmp/urlFile"; echo; } | 

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

{ <"/tmp/urlFile" tr -d '\r'; echo; } | 

ইনপুট ফাইলটি সুগঠিত হয়ে গেলে এবং একটি নতুন লাইনের সাথে শেষ না হলে, echoঅতিরিক্ত খালি লাইন যুক্ত করে। যেহেতু ইউআরএলগুলি খালি থাকতে পারে না, কেবল ফাঁকা রেখাগুলি উপেক্ষা করুন।

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

{ <"/tmp/urlFile" tr -d '\r'; echo; } | while read -r url
do
  if [ -z "$url" ]; then continue; fi
  
done

3

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

#!/bin/sh
while IFS= read -r line || [ "$line" ]; do 
    echo "line: $line"
done

$ printf 'foo\nbar' | sh ./read.sh 
line: foo
line: bar
$ printf 'foo\nbar\n' | sh ./read.sh 
line: foo
line: bar

1

আর একটি উপায় এটির মতো হবে:

যখন পড়াটি লাইনের শেষের পরিবর্তে ফাইলের শেষের দিকে পৌঁছে তখন এটি ডেটাতে পড়ে এবং ভেরিয়েবলগুলিকে নির্ধারণ করে তবে এটি একটি শূন্য-স্থিতি স্থিতি নিয়ে উপস্থিত হয়। আপনার লুপটি যদি "পড়ার সময় তৈরি করা হয়; জিনিসগুলি করুন; সম্পন্ন করুন

সুতরাং সরাসরি পঠনের প্রস্থান স্থিতিটি পরীক্ষা করার পরিবর্তে একটি পতাকা পরীক্ষা করুন, এবং রিড কমান্ডটি লুপের প্রধান অংশ থেকে এই পতাকাটি সেট করুন। পঠনের প্রস্থান স্থিতি নির্বিশেষে পুরো লুপ বডিটি চলে, কারণ পঠনটি অন্যগুলির মতো লুপের কমান্ডের তালিকার একটি মাত্র ছিল, লুপটি আদৌ চালিত হবে কিনা তা সিদ্ধান্ত নেওয়ার কারণ নয় not

DONE=false
until $DONE ;do
read || DONE=true
echo $REPLY 
done < /tmp/urlFile

এখান থেকে রেফার করা ।


1
বিড়াল "/ tmp / urlFile" | ইউআরএল পড়ার সময়
করা
    প্রতিধ্বনি $ url
সম্পন্ন

এটি একটি অকেজো ব্যবহারcat

হাস্যকরভাবে, আপনি catএখানে প্রক্রিয়াটিকে আসলে দরকারী কিছু দিয়ে প্রতিস্থাপন করতে পারেন : একটি সরঞ্জাম যা পসিক্স সিস্টেমে অনুপস্থিত নতুন লাইন যুক্ত করার জন্য এবং ফাইলটিকে একটি সঠিক পসিক্স পাঠ্য ফাইল হিসাবে তৈরি করতে পারে।

sed -e '। a \' "/ tmp / urlFile" | ইউআরএল পড়ার সময়
করা
    printf "% s s n" "$ {url}"
সম্পন্ন

আরও পড়া


1
সিডের আচরণ POSIX দ্বারা নির্ধারিত হয় যখন ইনপুটটি যদিও কোনও নতুন লাইনের অক্ষরে শেষ হয় না; এছাড়াও যখন LINE_MAX এর চেয়ে বড় লাইন থাকে, যখন এর ক্ষেত্রে আচরণগুলি readনির্দিষ্ট করা হয়।
স্টাফেন চেজেলাস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.