ফাইল নাম = এবং এর চারপাশে কীভাবে কাজ করা যায় তা কেন কেন বিশ্রীকরণ বন্ধ হয়ে অপেক্ষা করবে?


25
awk 'processing_script_here' my=file.txt

মনে হচ্ছে বন্ধ হয়ে অনির্দিষ্টকালের জন্য অপেক্ষা করুন ...
এখানে কী চলছে এবং আমি কীভাবে এটি কাজ করব?


উত্তর:


19

ক্রিস যেমন বলেছে , ফর্মের আর্গুমেন্টগুলি variablename=anythingপরিবর্তনশীল অ্যাসাইনমেন্ট হিসাবে বিবেচনা করা হয় (যেগুলি যুক্তিগুলির -v var=valueপূর্বে যেগুলি (নতুন) করা হয় তার বিপরীতে যেগুলি যুক্তিগুলি প্রক্রিয়া করা হয় তখন BEGINইনপুট ফাইলের নামগুলির পরিবর্তে সম্পাদিত হয় )।

এটি এই জাতীয় কাজে কার্যকর হতে পারে:

awk '{print $1}' FS=/ RS='\n' file1 FS='\n' RS= file2

যেখানে আপনি ফাইলের জন্য আলাদা FS/ নির্দিষ্ট করতে পারেন RS। এটি সাধারণত:

awk '!file1_processed{a[$0]; next}; {...}' file1 file1_processed=1 file2

এটির একটি নিরাপদ সংস্করণ:

awk 'NR==FNR{a[$0]; next}; {...}' file1 file2

(যা file1খালি থাকলে কাজ করে না )

তবে সেই পথে আসে যখন আপনার ফাইল রয়েছে যার নামতে =অক্ষর রয়েছে ।

এখন, কেবল তখনই সমস্যা যখন প্রথমটির =বাকীটি একটি বৈধ awkপরিবর্তনশীল নাম name

যাতে একটি বৈধ পরিবর্তনশীল নাম গঠন করে awkতা হ'ল তার চেয়ে কঠোর sh

পসিক্স এর মতো কিছু হওয়া দরকার:

[_a-zA-Z][_a-zA-Z0-9]*

কেবল পোর্টেবল অক্ষর সেট অক্ষরের সাথে। তবে /usr/xpg4/bin/awkসোলারিস ১১-এর অন্ততপক্ষে সেই ক্ষেত্রে সামঞ্জস্যপূর্ণ নয় এবং স্থানীয়ভাবে কোনও বর্ণমালার অক্ষরকে কেবল একটি-জেডএ-জেড নয়, চলক নামে অনুমতি দেয়।

তাই মত একটি আর্গুমেন্ট x+y=fooবা =barবা ./foo=barএখনও একটি ইনপুট ফাইল নাম এবং একটি কাজ হিসাবে গণ্য হবে যেমন কি বাম প্রথম =একটি বৈধ পরিবর্তনশীল নাম নয়। বাস্তবায়ন এবং লোকালের Stéphane=Chazelas.txtউপর নির্ভর করে মে বা না যেমন মত যুক্তি awk

এজন্যই কেন এডকে, এটি ব্যবহারের পরামর্শ দেওয়া হচ্ছে:

awk '...' ./*.txt

পরিবর্তে

awk '...' *.txt

উদাহরণস্বরূপ সমস্যা এড়াতে যদি আপনি গ্যারান্টি দিতে না পারেন তবে txtফাইলগুলির নামের সাথে =অক্ষর থাকবে না ।

এছাড়াও, সতর্কতা অবলম্বন করুন যে -vfoo=bar.txtযদি আপনি ব্যবহার করেন তবে এই জাতীয় যুক্তিটিকে বিকল্প হিসাবে বিবেচনা করা যেতে পারে:

awk -f file.awk -vfoo=bar.txt

( 1.28.0 এর পূর্বে ব্যস্তবক্স সংস্করণগুলির awk '{code}' -vfoo=bar.txtসাথে প্রযোজ্য awk, এটি সম্পর্কিত বাগ রিপোর্ট দেখুন )।

আবার, এর ./*.txtচারপাশে কাজ করে (একটি ./উপসর্গ ব্যবহার করা এমন একটি ফাইলের সাথে সহায়তা করে -যা অন্যথায় পরিবর্তে স্ট্যান্ডার্ড ইনপুটawk হিসাবে বোঝে )।

সে কারণেই

#! /usr/bin/awk -f

shebangs সত্যিই কাজ করে না। যদিও একটি বিবৃতিতে মানগুলি (একটি উপসর্গ যুক্ত করুন) ঠিক করে var=valueচারপাশে কাজ করা যেতে পারে :ARGV./BEGIN

#! /usr/bin/awk -f
BEGIN {
  for (i = 1; i < ARGC; i++)
    if (ARGV[i] ~ /^[_[:alpha:]][_[:alnum:]]*=/)
      ARGV[i] = "./" ARGV[i]
}
# rest of awk script

এটি বিকল্পগুলির সাথে সহায়তা করবে না কারণ সেগুলি স্ক্রিপ্ট awkনয় বরং দেখা যায় awk

এই ./উপসর্গটি ব্যবহার করার একটি সম্ভাব্য কসমেটিক সমস্যা এটি শেষ হয় FILENAMEতবে আপনি এটি না চাইলে সর্বদা substr(FILENAME, 3)এটি মুছতে ব্যবহার করতে পারেন।

জিএনইউ বাস্তবায়ন awkতার -Eবিকল্প সহ এই সমস্ত সমস্যার সমাধান করে ।

এর পরে -E, গোক কেবল awkস্ক্রিপ্টের পাথের প্রত্যাশা করে (যেখানে -এখনও স্টিডিন মানে) এবং তারপরে কেবল ইনপুট ফাইল পাথের একটি তালিকা (এবং সেখানে, এমনকি এমনকি -বিশেষভাবে চিকিত্সা করা হয় না )।

এটি বিশেষভাবে জন্য ডিজাইন করা হয়েছে:

#! /usr/bin/gawk -E

shebangs যেখানে আর্গুমেন্টের তালিকা সর্বদা ইনপুট ফাইল হয় (নোট করুন যে আপনি এখনও ARGVএকটি BEGINবিবৃতিতে সেই তালিকাটি সম্পাদনা করতে পারেন )।

আপনি এটি হিসাবে এটি ব্যবহার করতে পারেন:

gawk -e '...awk code here...' -E /dev/null *.txt

আমরা -Eখালি স্ক্রিপ্ট ( /dev/null) ব্যবহার করি কেবল *.txtএটির জন্য এটি পরবর্তী =অক্ষরগুলি সর্বদা ইনপুট ফাইল হিসাবে বিবেচিত হবে তা নিশ্চিত করার জন্য they


আমি দেখতে পাচ্ছি না যে স্পষ্ট পথটি FILENAME এ শেষ পর্যন্ত কীভাবে সমস্যা হয়। উভয় ক্ষেত্রেই awk স্ক্রিপ্ট সাধারণ, যা ক্ষেত্রে এটি (তত্সহ কিন্তু সীমাবদ্ধ নয় FILENAME- এর মধ্যে শেষ পর্যন্ত পাথ সব ধরনের হ্যান্ডেল করা হয় ../foo, /path/to/fooযে একটি ভিন্ন এনকোডিং রয়েছে এবং পাথ) - যা কেস substr(FILENAME,3)যথেষ্ট হবে না, বা এটা একটি এক শট স্ক্রিপ্ট ব্যবহারকারী যেখানে মূলত জানেন ফাইলের নামের রয়েছে - যে ক্ষেত্রে s এ / তিনি সম্ভবত তাদের কাউকে সম্বলিত বিরক্ত করা উচিত নয় =পারেন ;-)
mosvy

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

@ মোসবি, হ্যাঁ ধারণাটি হল আপনি সেই উপাচারটি ব্যবহার করতে ./উপসর্গটি ব্যবহার করতে চান awk(মিস) বৈশিষ্ট্যটি কিন্তু তারপরে আপনি ./ফলাফলটি শেষ করতে পারেন যা আপনি মুছে ফেলতে চাইতে পারেন। ফাইলের প্রথম লাইনে একটি নির্দিষ্ট স্ট্রিং রয়েছে কিনা তা পরীক্ষা করে দেখুন কীভাবে? উদাহরণ হিসাবে।
স্টাফেন চেজেলাস

কেবল স্থানীয় নয় (এই ডিরেক্টরিটির সাথে সম্পর্কিত) ./এটিও বিশ্বব্যাপী (পরম পথ) /যা বিশ্রী যুক্তিটিকে ফাইল হিসাবে ব্যাখ্যা করে।
ইসহাক

21

বেশিরভাগ সংস্করণের সংস্করণগুলিতে, প্রোগ্রামটি কার্যকর করার পরে যুক্তিগুলি হয়:

  1. একটি নথি
  2. ফর্ম একটি অ্যাসাইনমেন্ট x=y

যেহেতু আপনার ফাইলের নাম কেস # 2 হিসাবে ব্যাখ্যা করা হচ্ছে, অ্যাডাব্লক এখনও স্টিডিনে কিছু পড়ার জন্য অপেক্ষা করছে (যেহেতু এটি বুঝতে পারে না যে কোনও ফাইল নাম পাস হয়েছে)।

বহনযোগ্যভাবে, এই আচরণটি পসিক্সে নথিভুক্ত করা হয় :

নিম্নলিখিত দুটি ধরণের আর্গুমেন্টের মধ্যে দুটি মিলে যেতে পারে:

  • ফাইল: পড়ার মতো ইনপুট রয়েছে এমন কোনও ফাইলের একটি পাথের নাম, যা প্রোগ্রামে নিদর্শনগুলির সেটগুলির সাথে মিলে যায়। যদি কোনও ফাইল অপারেন্ড নির্দিষ্ট না করা হয় বা কোনও ফাইল অপারেন্ড '-' হয় তবে স্ট্যান্ডার্ড ইনপুট ব্যবহার করা হবে।
  • অ্যাসাইনমেন্ট: একটি অপারেন্ড যা পোর্টেবল অক্ষর সেট থেকে আন্ডারস্কোর বা বর্ণানুক্রমিক অক্ষর দিয়ে শুরু হয় (আইইইই স্ট্যান্ড 1003.1-2001, বিভাগ 6.1, পোর্টেবল ক্যারেক্টার সেটের বেস সংজ্ঞা ভলিউমে টেবিলটি দেখুন), তারপরে আন্ডারস্কোর, অঙ্কগুলি, এবং পোর্টেবল অক্ষর সেট থেকে বর্ণমালা, '=' অক্ষর দ্বারা অনুসরণ করা হয়, একটি নামের পরিবর্তে একটি চলক অ্যাসাইনমেন্ট নির্দিষ্ট করে।

এর মতো, বহনযোগ্যভাবে, আপনার কাছে কয়েকটি বিকল্প রয়েছে (# 1 সম্ভবত স্বল্পতম হস্তক্ষেপমূলক):

  1. ব্যবহার করুন awk ... ./my=file, যেহেতু .এটি "পোর্টেবল অক্ষর সেট থেকে একটি আন্ডারস্কোর বা বর্ণমালা অক্ষর নয়" এর পাশ দিয়ে গেছে ।
  2. স্টিডিন ব্যবহার করে ফাইলটি রাখুন awk ... < my=file। তবে এটি একাধিক ফাইলের সাথে ভালভাবে কাজ করে না।
  3. অস্থায়ীভাবে ফাইলটিতে একটি হার্ডলিঙ্ক তৈরি করুন এবং এটি ব্যবহার করুন। আপনি এর মতো কিছু করতে পারেন ln my=file my_fileএবং তারপরে my_fileস্বাভাবিক হিসাবে ব্যবহার করতে পারেন । কোনও অনুলিপি সম্পাদন করা হবে না এবং উভয় ফাইলই একই ডেটা এবং ইনোড মেটাডেটা দ্বারা ব্যাক হবে। এটি ব্যবহারের পরে, তৈরি হওয়া লিঙ্কটি সরিয়ে ফেলা নিরাপদ কারণ ইনোডের উল্লেখের সংখ্যাটি এখনও 0 এর বেশি হবে।

6
./my=file কাজ করে না ? % awk 'processing_script_here' ./my=file.txt awk: fatal: cannot open file ./my=file.txt' for reading (No such file or directory). এটি পোর্টেবল হওয়া উচিত কারণ ./myবৈধ পরিবর্তনশীল নাম নয়, সুতরাং সেইভাবে পার্স করা উচিত নয়।
স্টিফেন হ্যারিস

2
যে POSIX টেক্সট বলেছেন, সমস্যা শুধুমাত্র যখন প্রথম =পূর্বে হয় , একটি আন্ডারস্কোর বা পোর্টেবল অক্ষর সেট থেকে বর্ণানুক্রমিক অক্ষর (আইইইই এসটিডি 1003.1-2001, বিভাগ 6.1, পোর্টেবল অক্ষর সেট এর বেজ সংজ্ঞা আয়তনের টেবিল দেখুন) পোর্টেবল অক্ষর সেট থেকে আন্ডারস্কোর, অঙ্ক এবং বর্ণমালার ক্রম অনুসরণ করে । তাই মত একটি ফাইল পাথ ++foo=bar.txtঅথবা =fooবা ./foo=barসব ঠিক আছ যে .বা +একটি নয় [_a-zA-Z]
স্টাফেন চেজেলাস

1
@ সার্জি কলোডিএজনি এজেড শেলের বাহ্যিক, তাই আপনি যা ব্যবহার করেন তা বিবেচ্য নয়। ./my=fileভারব্যাটিম মাধ্যমে পাস করা হবে।
ক্রিস ডাউন

1
@SergiyKolodyazhnyy জন্য একই awk '{print $1,$2}' /etc/passwd। মুল বক্তব্যটি হ'ল শেলটি ফাইলটিকে ওজেকের বিপরীতে খোলার কারণে এটি অনুসন্ধানযোগ্য হবে কিনা তা কোনও পার্থক্য নেই। প্রকৃতপক্ষে, আপনি এখানে প্রথম রেকর্ডের শেষে ফিরে খোঁজ নিতে awk '{exit}' < /etc/passwdআশা awkকরবেন exitযাতে এটি স্টিডিনের মধ্যে অবস্থানটি ছেড়ে যায় তা নিশ্চিত করে নিন। পসিক্সের এটি প্রয়োজন। /usr/xpg4/bin/awkএটি সোলারিসে করে না, তবে জিএনইউ / লিনাক্সেও তা করবে gawkনা mawkবলে মনে হচ্ছে না।
স্টাফেন চেজেলাস

3
@ মোসবি, pubs.opengroup.org/onlinepubs/9699919799/utilities/… এ ইনপুট ফাইলগুলি বিভাগটি দেখুন এটি নিয়মিত ফাইলগুলির সাথে কেবল কার্যকর হয় যখন আপনি কোনও ফাইল কেটে ফেলতে চান বা এতে ডেটা লিখতে চান awkযে অবস্থান দ্বারা চিহ্নিত একটি অবস্থান ।
স্টাফেন চেজেলাস

3

গাওক ডকুমেন্টেশন উদ্ধৃত করতে (জোর দেওয়া নোট জোর দেওয়া):

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

কমান্ড কেন থামবে এবং অপেক্ষা করবে? কারণ ফর্মটিতে উপরোক্ত সংজ্ঞা অনুসারে awk 'processing_script_here' my=file.txt কোনও ফাইল নির্দিষ্ট করা হয়নি - my=file.txtভেরিয়েবল অ্যাসাইনমেন্ট হিসাবে ব্যাখ্যা করা হয়, এবং কোনও ফাইল সংজ্ঞায়িত না হলে awkস্টিডিন পড়বে (এটি থেকেও স্পষ্ট হয় straceযে এই জাতীয় কমান্ডে অ্যাড্ক সিস্কেলের জন্য অপেক্ষা করছে) read(0,'...)

এটাও মধ্যে নথিভুক্ত করা POSIX awk নির্দিষ্টকরণের , OPERANDS অধ্যায় কর এবং দেখ বরাদ্দকরণ যে অংশ)

পরিবর্তনশীল অ্যাসাইনমেন্টটি প্রতিটি awk '{print foo}' foo=bar /etc/passwdমান foo/ / ইত্যাদি / পাসডাব্লুডির জন্য মুদ্রিত যে মানটিতে প্রমাণিত হয় । সুনির্দিষ্ট ./foo=barবা পুরো পথটি কাজ করে।

লক্ষ্য করুন চলমান straceউপর awk '1' foo=barসেইসাথে সঙ্গে চেক cat foo=barদেখায় যে, এই awk-নির্দিষ্ট ব্যাপার, এবং যুক্তি পাস execve প্রদর্শনী ফাইলের নাম, তাই শাঁস এই ক্ষেত্রে env পরিবর্তনশীল বরাদ্দকরণ সঙ্গে কিছুই করার আছে।

অতিরিক্তভাবে, দয়া করে নোট করুন যে awk '...script...' foo=barশেল দ্বারা পরিবেশ পরিবর্তনশীল তৈরির কারণ হবে না, যেহেতু পরিবেশ পরিবর্তনশীল অ্যাসাইনমেন্টগুলি কার্যকর হওয়ার জন্য একটি আদেশের আগে থাকা উচিত। পসিক্স শেল ব্যাকরণ বিধিমালা , পয়েন্ট নম্বর See দেখুন Additionally অতিরিক্তভাবে এটি মাধ্যমে যাচাই করা যেতে পারেawk '{print ENVIRON["foo"]}' foo=bar /etc/passwd

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.