রুবিতে এসটিডিনের সাথে সেরা অনুশীলনগুলি?


307

আমি রুবিতে কমান্ড লাইন ইনপুটটি মোকাবেলা করতে চাই:

> cat input.txt | myprog.rb
> myprog.rb < input.txt
> myprog.rb arg1 arg2 arg3 ...

এটা করার সবচেয়ে ভালো উপায় কি? বিশেষত আমি ফাঁকা STDIN নিয়ে কাজ করতে চাই এবং আমি একটি মার্জিত সমাধানের আশা করি।

#!/usr/bin/env ruby

STDIN.read.split("\n").each do |a|
   puts a
end

ARGV.each do |b|
    puts b
end

5
কেবল একটি ছোট্ট নোট: আপনি যে প্রথম দুটি কমান্ড লাইন দিয়েছেন সেটি দৃষ্টিকোণ থেকে একরকম myprog.rb: input.txtফাইলটি স্টিডিনের সাথে সংযুক্ত ; শেলটি আপনার জন্য এটি পরিচালনা করে।
মী

6
^^ এটিকে প্রায়শই "বিড়ালের অকেজো ব্যবহার" হিসাবে উল্লেখ করা হয়, আপনি এটি দেখতে পাবেন।
স্টিভ কেহলেট

18
@ স্টিভ কেহলেট যাইহোক আমি বিশ্বাস করি এটি আরও চতুরতার সাথে "বিড়ালের অপব্যবহার" হিসাবে উল্লেখ করা হয়েছে
ওয়ানচিলডুড

উত্তর:


403

আমার অস্পষ্ট রুবি সংগ্রহের মধ্যে আমি কিছু জিনিস পেয়েছি।

সুতরাং, রুবিতে, ইউনিক্স কমান্ডের একটি সাধারণ নো-বেলস বাস্তবায়ন catহবে:

#!/usr/bin/env ruby
puts ARGF.read

ARGFআপনার ইনপুট আসে যখন আপনার বন্ধু হয়; এটি একটি ভার্চুয়াল ফাইল যা নামকৃত ফাইলগুলি বা এসটিডিইএন থেকে সমস্ত ইনপুট পায়।

ARGF.each_with_index do |line, idx|
    print ARGF.filename, ":", idx, ";", line
end

# print all the lines in every file passed via command line that contains login
ARGF.each do |line|
    puts line if line =~ /login/
end

ধার্মিকতার জন্য ধন্যবাদ আমরা রুবিতে হীরা অপারেটরটি পাইনি, তবে আমরা ARGFপ্রতিস্থাপন হিসাবে পেয়েছি । অস্পষ্ট যদিও, এটি আসলে দরকারী হতে দেখা যাচ্ছে। এই প্রোগ্রামটি বিবেচনা করুন, যা -iকমান্ড-লাইনে উল্লিখিত প্রতিটি ফাইলের জন্য কপিরাইট শিরোলেখগুলিকে স্থানের (অন্য পার্লিজমকে ধন্যবাদ ) প্রদান করে:

#!/usr/bin/env ruby -i

Header = DATA.read

ARGF.each_line do |e|
  puts Header if ARGF.pos - e.length == 0
  puts e
end

__END__
#--
# Copyright (C) 2007 Fancypants, Inc.
#++

ক্রেডিট:


12
এআরজিএফ হ'ল উপায়। এটি রুবি এর চারপাশে ফ্যাশনগুলিতে স্ট্যান্ড এবং স্টিন পরিচালনা করার জন্য নির্মিত।
পিস্তোস

1
(এটি দেখে এবং আপনাকে ভেবে দেখে) সেই ক্রেডিটগুলি আবার: Blog.nicksieger.com/articles/2007/10/06/…
দেউ

ওঁটা খুব সুন্দর. AWK যেভাবে কাজ করে (শূন্য বা ন্যূনতম কথোপকথন সহ) অনুকরণ করার জন্য একটি দুর্দান্ত প্যাটার্ন রয়েছে সেখানে আমার দিনটি সম্পূর্ণ হবে। :-)
হবে

সম্ভবত লক্ষ্য করা উচিত যে idxপ্রতিটি পৃথক ফাইলের জন্য লাইন নম্বর না করে ভার্চুয়াল ফাইলটিতে সমস্ত ইনপুট যুক্ত করে "লাইন নম্বর" হবে।
অ্যালেক জ্যাকবসন

এই নোট #!/usr/bin/env ruby -i: লাইন লিনাক্স কাজ করে না stackoverflow.com/q/4303128/735926
bfontaine

43

রুবি এসটিডিআইএন হ্যান্ডেল করার অন্য একটি উপায় সরবরাহ করে: -ন পতাকা। এটি আপনার পুরো প্রোগ্রামটিকে STDIN এর ওপরে লুপের অভ্যন্তরে হিসাবে গণ্য করে (কমান্ড লাইন আর্গ হিসাবে ফাইলগুলি সহ)। উদাহরণস্বরূপ নিম্নলিখিত 1-লাইনের স্ক্রিপ্ট দেখুন:

#!/usr/bin/env ruby -n

#example.rb

puts "hello: #{$_}" #prepend 'hello:' to each line from STDIN

#these will all work:
# ./example.rb < input.txt
# cat input.txt | ./example.rb
# ./example.rb input.txt

8
#!/usr/bin/env ruby -n"রুবি-এন" একমাত্র যুক্তি হিসাবে / ইউএসআর / বিন / এনভিতে পাস হবে বলে তিন-পার্টির শেবাং কাজ করবে না। আরও তথ্যের জন্য এই উত্তর দেখুন । স্পষ্টভাবে চালিত হলে স্ক্রিপ্টটি কাজ করবেruby -n script.rb
আর্টেম

5
@ জেডিজল: এটি ওএসএক্সে কাজ করে, তবে লিনাক্সে নয় - এবং ঠিক এটিই সমস্যা: এটি বহনযোগ্য নয় ।
mklement0

32

আপনার কী প্রয়োজন তা আমি নিশ্চিত নই, তবে আমি এই জাতীয় কিছু ব্যবহার করব:

#!/usr/bin/env ruby

until ARGV.empty? do
  puts "From arguments: #{ARGV.shift}"
end

while a = gets
  puts "From stdin: #{a}"
end

নোট করুন যেহেতু এআরজিভি অ্যারে প্রথমে ফাঁকা gets , রুবি যুক্তিটি পাঠ্য ফাইল হিসাবে ব্যাখ্যা করার চেষ্টা করবে না যা থেকে পড়তে হবে (আচরণটি পার্লের উত্তরাধিকার সূত্রে প্রাপ্ত)।

স্টিডিন খালি থাকলে বা কোনও যুক্তি না থাকলে কিছুই মুদ্রিত হয় না।

কয়েকটি পরীক্ষার কেস:

$ cat input.txt | ./myprog.rb
From stdin: line 1
From stdin: line 2

$ ./myprog.rb arg1 arg2 arg3
From arguments: arg1
From arguments: arg2
From arguments: arg3
hi!
From stdin: hi!

18

এরকম কিছু সম্ভবত?

#/usr/bin/env ruby

if $stdin.tty?
  ARGV.each do |file|
    puts "do something with this file: #{file}"
  end
else
  $stdin.each_line do |line|
    puts "do something with this line: #{line}"
  end
end

উদাহরণ:

> cat input.txt | ./myprog.rb
do something with this line: this
do something with this line: is
do something with this line: a
do something with this line: test
> ./myprog.rb < input.txt 
do something with this line: this
do something with this line: is
do something with this line: a
do something with this line: test
> ./myprog.rb arg1 arg2 arg3
do something with this file: arg1
do something with this file: arg2
do something with this file: arg3

স্টিডিনের পাঠ্য হওয়া দরকার নেই। নোটরিয়াস টেক্সট নয় উদাহরণস্বরূপ কিছু প্রকারের কমপ্রেস / কমপ্রেস করা। (প্রতিটি_লাইন কেবলমাত্র এসকিআইয়ের জন্য প্রস্তুত)। প্রতিটি_বিয়েতে পারে?
জোন্কে

12
while STDIN.gets
  puts $_
end

while ARGF.gets
  puts $_
end

এটি পার্ল দ্বারা অনুপ্রাণিত:

while(<STDIN>){
  print "$_\n"
}

4
হ্যাঁ হ্যাঁ, সরলতা এবং পাঠযোগ্যতার জন্য! ওহ না, অপেক্ষা করুন, সে '$ _' কী? স্ট্যাক ওভারফ্লোতে ইংরেজি ব্যবহার করুন!


1

আমি এটি যুক্ত করব ARGFপরামিতিগুলির সাথে ব্যবহার করার জন্য , আপনাকে ARGVকল করার আগে পরিষ্কার করতে হবে ARGF.each। এর কারণ এটি যে ARGFকোনও কিছুকে ARGVফাইলের নাম হিসাবে বিবেচনা করবে এবং সেখান থেকে প্রথমে লাইনগুলি পড়বে।

এখানে 'টি' বাস্তবায়ন উদাহরণ:

File.open(ARGV[0], 'w') do |file|
  ARGV.clear

  ARGF.each do |line|
    puts line
    file.write(line)
  end
end

1

আমি এরকম কিছু করি:

all_lines = ""
ARGV.each do |line|
  all_lines << line + "\n"
end
puts all_lines

0

দেখে মনে হচ্ছে বেশিরভাগ উত্তরগুলি আর্গুমেন্টগুলি স্ট্যান্ডিনের কন্টেন্টযুক্ত ফাইলের নাম। সমস্ত কিছু নীচে কেবল যুক্তি হিসাবে বিবেচনা করা হয়। যদি STDIN টিটিওয়াই থেকে হয় তবে তা উপেক্ষা করা হবে।

$ cat tstarg.rb

while a=(ARGV.shift or (!STDIN.tty? and STDIN.gets) )
  puts a
end

যে কোনও যুক্তি বা স্টিডিন খালি থাকতে পারে বা ডেটা থাকতে পারে।

$ cat numbers 
1
2
3
4
5
$ ./tstarg.rb a b c < numbers
a
b
c
1
2
3
4
5
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.