سؤال

أريد أن أفعل هذا:

  1. تشغيل الأوامر
  2. التقاط الإخراج
  3. حدد خط
  4. حدد عمود من هذا الخط

وعلى سبيل المثال, دعونا نقول كنت ترغب في الحصول على اسم الأمر من $PID (يرجى ملاحظة أن هذا هو مجرد مثال ، أنا لا أقترح هذا هو أسهل طريقة للحصول على أمر اسم من عملية id - مشكلتي الحقيقية هي مع آخر الأمر الذي تنسيق الإخراج لا أستطيع التحكم).

إذا كنت تعمل ps أحصل على:


  PID TTY          TIME CMD
11383 pts/1    00:00:00 bash
11771 pts/1    00:00:00 ps

الآن أفعل ps | egrep 11383 والحصول على

11383 pts/1    00:00:00 bash

الخطوة التالية: ps | egrep 11383 | cut -d" " -f 4.الناتج هو:

<absolutely nothing/>

المشكلة هي أن cut تخفيضات الانتاج واحد المساحات ، ps يضيف بعض المساحات بين 2 و 3 أعمدة للحفاظ على بعض الشبه من الجدول ، cut يختار سلسلة فارغة.بالطبع يمكنني استخدام cut لتحديد 7 و ليس 4 الميدانية ، ولكن كيف يمكن أن أعرف خصيصا عندما خرج هو متغير غير معروف مسبقا.

هل كانت مفيدة؟

المحلول

واحد طريقة سهلة لإضافة تمريرة من tr للضغط على أي تكرار مجال فواصل من:

$ ps | egrep 11383 | tr -s ' ' | cut -d ' ' -f 4

نصائح أخرى

أعتقد أن أبسط طريقة هي استخدام awk.على سبيل المثال:

$ echo "11383 pts/1    00:00:00 bash" | awk '{ print $4; }'
bash

يرجى ملاحظة أن tr -s ' ' الخيار سوف لا إزالة أي واحد المسافات البادئة.إذا كان العمود محاذاة إلى اليمين (كما هو الحال مع ps pid)...

$ ps h -o pid,user -C ssh,sshd | tr -s " "
 1543 root
19645 root
19731 root

ثم قطع سيؤدي إلى سطر فارغ عن بعض من تلك الحقول إذا كان العمود الأول:

$ <previous command> | cut -d ' ' -f1

19645
19731

ما لم يسبق ذلك مع الفضاء ، ومن الواضح

$ <command> | sed -e "s/.*/ &/" | tr -s " "

الآن في هذه الحالة بالذات من أرقام pid (لا أسماء) ، هناك وظيفة تسمى pgrep:

$ pgrep ssh


وظائف شل

ولكن بشكل عام فإنه في الواقع لا يزال من الممكن استخدام وظائف شل بأسلوب موجز ، لأن هناك شيء أنيق حول read الأمر:

$ <command> | while read a b; do echo $a; done

المعلمة الأولى للقراءة ، a, يختار العمود الأول, و إذا كان هناك أكثر من ذلك ، كل شيء آخر سيتم وضعها في b.ونتيجة لذلك أنت لا تحتاج أكثر من المتغيرات من رقم العمود +1.

لذلك ،

while read a b c d; do echo $c; done

ثم خرج 3 عمود.كما ورد في تعليقي...

مجموعة الأنابيب قراءة سيتم تنفيذها في بيئة لا تمرير المتغيرات إلى استدعاء البرنامج النصي.

out=$(ps whatever | { read a b c d; echo $c; })

arr=($(ps whatever | { read a b c d; echo $c $b; }))
echo ${arr[1]}     # will output 'b'`


مجموعة الحل

لذلك نحن ثم في نهاية المطاف مع الإجابة من قبل @frayser الذي هو استخدام قذيفة متغير المحاذير التي التخلف إلى الفضاء ، إلى تقسيم السلسلة إلى صفيف.أنها لا تعمل إلا في باش على الرغم من.داش والرماد لا تدعم ذلك.لقد كان وقتا عصيبا حقا تقسيم السلسلة إلى المكونات في Busybox شيء.فمن السهل بما فيه الكفاية للحصول على مكون واحد (مثلا ، باستخدام awk) ثم كرر ذلك لكل معلمة تحتاج إليها.ولكن بعد ذلك كنت في نهاية المطاف يدعو مرارا وتكرارا awk على نفس الخط ، أو بشكل متكرر باستخدام قراءة كتلة مع صدى على نفس الخط.وهي ليست فعالة أو جميلة.إذا كنت في نهاية المطاف تقسيم باستخدام ${name%% *} وهلم جرا.يجعلك تتوق إلى بعض الثعبان المهارات لأنه في الواقع shell scripting ليست الكثير من المرح بعد الآن إذا كان النصف أو أكثر من الميزات التي اعتادوا عليها ، ولت.ولكن يمكن أن نفترض أنه حتى الثعبان لن يكون مثبتا على مثل هذا النظام ، وأنه لم يكن ;-).

محاولة

ps |&
while read -p first second third fourth etc ; do
   if [[ $first == '11383' ]]
   then
       echo got: $fourth
   fi       
done

على غرار brianegge هو awk الحل هنا هو Perl ما يعادلها:

ps | egrep 11383 | perl -lane 'print $F[3]'

-a تمكن autosplit الوضعية التي بملء @F صف مع عمود بيانات.
استخدام -F, إذا كانت البيانات الخاصة بك هو بفواصل بدلا من الفضاء محدد.

المجال 3 طبع منذ بيرل يبدأ العد من 0 بدلا من 1

الحصول على الخط الصحيح (مثلا خط لا.6) يتم مع الرأس والذيل الكلمة الصحيحة (كلمة لا.4) يمكن التقاطها مع awk:

command|head -n 6|tail -n 1|awk '{print $4}'

باستخدام مجموعة المتغيرات

set $(ps | egrep "^11383 "); echo $4

أو

A=( $(ps | egrep "^11383 ") ) ; echo ${A[3]}

بدلا من كل هذه greps و الأشياء أنصحك أن تستخدم ps قدرات تغيير تنسيق الإخراج.

ps -o cmd= -p 12345

يمكنك الحصول على cmmand خط العملية مع pid المحدد و لا شيء آخر.

هذا هو POSIX conformant و قد يكون مما يعتبر المحمولة.

الأمر الخاص بك

ps | egrep 11383 | cut -d" " -f 4

يفتقد tr -s للضغط على المساحات الاسترخاء يفسر في جوابه.

ومع ذلك, ربما كنت ترغب في استخدام awk, لأنه يتعامل مع كل هذه الإجراءات في أمر واحد:

ps | awk '/11383/ {print $4}'

هذا يطبع 4 عمود في تلك الخطوط التي تحتوي على 11383.إذا كنت تريد أن المباراة 11383 إذا كان يبدو في بداية السطر, ثم يمكنك أن تقول ps | awk '/^11383/ {print $4}'.

باش set سيتم تحليل جميع الإخراج في موقف المعلمات.

على سبيل المثال ، set $(free -h) الأوامر ، echo $7 سوف تظهر "Mem:"

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top