কমান্ডের আর্গুমেন্ট হিসাবে কোনও পাঠ্য ফাইলের প্রতিটি লাইন কীভাবে পাস করবেন?


42

আমি একটি স্ক্রিপ্ট লিখতে চাইছি যা একটি .txtফাইল নামকে আর্গুমেন্ট হিসাবে গ্রহণ করে , ফাইল লাইনটি লাইন পড়ে এবং প্রতিটি লাইন একটি কমান্ডে পাস করে। উদাহরণস্বরূপ, এটি চলে command --option "LINE 1", তারপর command --option "LINE 2", ইত্যাদি। কমান্ডের আউটপুট অন্য কোনও ফাইলকে লেখা হয়। আমি কীভাবে এটি করতে যাব? কোথা থেকে শুরু করব জানি না।

উত্তর:


26

while readলুপ ব্যবহার করুন :

: > another_file  ## Truncate file.

while IFS= read -r LINE; do
    command --option "$LINE" >> another_file
done < file

অন্যটি হ'ল ব্লক দ্বারা আউটপুট পুনর্নির্দেশ:

while IFS= read -r LINE; do
    command --option "$LINE"
done < file > another_file

সর্বশেষে ফাইলটি খুলতে হবে:

exec 4> another_file

while IFS= read -r LINE; do
    command --option "$LINE" >&4
    echo xyz  ## Another optional command that sends output to stdout.
done < file

কমান্ড এক ইনপুট সার্চ পারেন, এটি একটি ভাল ধারণা ইনপুট জন্য অন্য FD ব্যবহার করতে যাতে কমান্ড তা খেয়ে জোড়া হবে না (এখানে অভিমানী হবে ksh, zshবা bashজন্য -u 3, ব্যবহার <&3পরিবর্তে portably):

while IFS= read -ru 3 LINE; do
    ...
done 3< file

শেষ পর্যন্ত আর্গুমেন্ট গ্রহণ করতে, আপনি এটি করতে পারেন:

#!/bin/bash

FILE=$1
ANOTHER_FILE=$2

exec 4> "$ANOTHER_FILE"

while IFS= read -ru 3 LINE; do
    command --option "$LINE" >&4
done 3< "$FILE"

কোনটি এটি হিসাবে চালাতে পারে:

bash script.sh file another_file

অতিরিক্ত ধারণা। সহ bash, ব্যবহার করুন readarray:

readarray -t LINES < "$FILE"

for LINE in "${LINES[@]}"; do
    ...
done

দ্রষ্টব্য: IFS=আপনি যদি শীর্ষস্থানীয় এবং অনুসরণের জায়গাগুলি ছাঁটাই করে রেখার মানগুলি মানা না করেন তবে বাদ দেওয়া যেতে পারে।


28

অন্য বিকল্প xargs

জিএনইউ সহ xargs:

< file xargs -I{} -d'\n' command --option {} other args

{} পাঠ্য লাইনের জন্য স্থানধারক।

অন্যদের xargsকাছে নেই -d, তবে কারও কারও -0কাছে NUL- সীমাবদ্ধ ইনপুট রয়েছে। তাদের সাথে, আপনি এটি করতে পারেন:

< file tr '\n' '\0' | xargs -0 -I{} command --option {} other args

ইউনিক্স-কনফর্মেন্ট সিস্টেমগুলিতে (পসিক্সে -Iisচ্ছিক এবং কেবল ইউনিক্স-কনফর্মেন্ট সিস্টেমগুলির জন্য প্রয়োজনীয়), আপনার দ্বারা প্রত্যাশিত ফর্ম্যাটে লাইনগুলি উদ্ধৃত করতে ইনপুটটিকে প্রস্রোস করতে হবে xargs:

< file sed 's/"/"\\""/g;s/.*/"&"/' |
  xargs -E '' -I{} command --option {} other args

তবে মনে রাখবেন যে কয়েকটি xargsবাস্তবায়নের পক্ষে সর্বোচ্চ আর্গুমেন্টের আকারের সীমাবদ্ধতা রয়েছে (উদাহরণস্বরূপ সোলারিসের 255, ইউনিক্স স্পেসিফিকেশন দ্বারা অনুমোদিত ন্যূনতম)।


থেকে রূপান্তরযোগ্য<file xargs -L 1 -I{} command --option {} other args
Iruvar

@iruvar, না, এটি উদ্ধৃতিগুলি প্রক্রিয়া করবে এবং কিছু ফাঁকা স্থান সরিয়ে ফেলবে।
স্টাফেন চেজেলাস

7

প্রশ্নের সঠিকভাবে রাখা:

#!/bin/bash

# xargs -n param sets how many lines from the input to send to the command

# Call command once per line
[[ -f $1 ]] && cat $1 | xargs -n1 command --option

# Call command with 2 lines as args, such as an openvpn password file
# [[ -f $1 ]] && cat $1 | xargs -n2 command --option

# Call command with all lines as args
# [[ -f $1 ]] && cat $1 | xargs command --option


3

আমি সবচেয়ে ভাল উত্তর পেয়েছি:

for i in `cat`; do "$cmd" "$i"; done < $file

সম্পাদনা করুন:

... চার বছর পরে ...

কয়েকটি ডাউন ভোট এবং আরও কিছু অভিজ্ঞতার পরে আমি এখন নিম্নলিখিতটি সুপারিশ করব

xargs -l COMMAND < file

3
এটি ফাইলের প্রতিটি শব্দের জন্য একবার কমান্ডটি চাওয়া হবে । এছাড়াও, আপনার সর্বদা শেল ভেরিয়েবলের উল্লেখ উল্লেখ করা উচিত (যেমন হিসাবে do "$cmd" "$i";) আপনার যদি না করার কারণ না থাকে; যদি ফাইলটি *একটি শব্দ হিসাবে নিজেই থাকে তবে আপনার কোডটি চলবে $cmd *, যা অবশ্যই বর্তমান ডিরেক্টরিটিতে ফাইলগুলির একটি তালিকা সহ কমান্ডটি চালিত করবে।
জি-ম্যান বলছেন 'পুনরায় ইনস্টল করুন মনিকা'

1
@ জি-ম্যান, ব্যতীত zsh, `cat`ইতিমধ্যে এটি সম্প্রসারণ করবে *(অব্যক্ত $iএখনও কিছু ওয়াইল্ডকার্ডকে বিস্তৃত করতে পারে (দ্বিতীয় রাউন্ড) যদি কিছুটির প্রসারিত হয় তবে `cat`)। যাই হোক না কেন, এই পদ্ধতির সত্যই ভুল।
স্টাফেন চেজেলাস

1
+1 টি। এটি দুর্দান্ত কাজ করবে, যদি প্রতিটি লাইনে ফাঁকা ছাড়াই ব্যবহৃত কমান্ডের জন্য প্রয়োজনীয় ইনপুট থাকে।
সুবিন সেবাস্তিয়ান

এটি প্রতিটি শব্দের উপর কাজ করে, প্রতিটি লাইনে এটির কোনও বৈকল্পিক রয়েছে?
thebunnyrules

প্রশ্নটি ছিল লাইন দ্বারা ফাইল নামগুলির একটি তালিকা প্রক্রিয়া করার জন্য।
স্টিফেন রোলার

2
    sed "s/'/'\\\\''/g;s/.*/\$* '&'/" <<\FILE |\
    sh -s -- command echo --option
all of the{&}se li$n\es 'are safely shell
quoted and handed to command as its last argument
following --option, and, here, before that echo
FILE

আউটপুট

--option all of the{&}se li$n\es 'are safely shell
--option quoted and handed to command as its last argument
--option following --option, and, here, before that echo

-2
ed file.txt
%g/^/s// /
2,$g/^/-,.j
1s/^/command/
wq
chmod 755 file.txt
./file.txt

একটি ফাইলের সমস্ত লাইন নিন এবং সেগুলি একটি একক কমান্ডে যুক্তি হিসাবে পাস করুন,

command line1 line2 line3 ....

আপনার যা দরকার তা যদি --optionপতাকা পূর্ববর্তী প্রতিটি লাইনে দ্বিতীয় কমান্ড পরিবর্তন করুন:

%g/^/s// --option /

1
এডি ... আসলেই ব্যবহারের জন্য কী?
ব্যবহারকারী2217522

3
আমি আপনাকে হ্রাস করি নি, তবে যে ব্যক্তির সম্ভবত এই কারণগুলি ছিল: (1) এটি প্রশ্নটি যা চায় তা করে না। এটি কমান্ড লাইনে ফাইলের সমস্ত বিষয়বস্তু সহ একবার কমান্ডটি আহ্বান করে; বরং প্রতি লাইনে একবার । (২) শেলটির জন্য বিশেষ যে অক্ষরগুলি (যা ফাইলটিতে থাকতে পারে) পরিচালনা করতে এটি কিছুই করে না; যেমন, ', ", <, >, ;, ইত্যাদি (3) এটি একটি অপ্রয়োজনীয় অস্থায়ী ফাইল তৈরি করে। (4) এর মতো জিনিসগুলি সাধারণত "এখানে নথি" দিয়ে করা হয়। (5) আপনার edআদেশগুলি আনাড়ি; প্রথম দুই কমান্ড কমে যাবে %s/^/ /এবং %j
জি-ম্যান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.