سؤال

هل هناك أي أمر bash يتيح لك الحصول على السطر n من STDOUT؟

وهذا يعني أن شيئًا من شأنه أن يستغرق هذا

$ ls -l
-rw-r--r--@ 1 root  wheel my.txt
-rw-r--r--@ 1 root  wheel files.txt
-rw-r--r--@ 1 root  wheel here.txt

وتفعل شيئا من هذا القبيل

$ ls -l | magic-command 2
-rw-r--r--@ 1 root  wheel files.txt

أدرك أن هذا سيكون ممارسة سيئة عند كتابة البرامج النصية التي يُقصد إعادة استخدامها، ولكن عند العمل مع الصدفة يوميًا، سيكون من المفيد بالنسبة لي أن أتمكن من تصفية STDOUT الخاص بي بهذه الطريقة.

أدرك أيضًا أن هذا سيكون أمرًا شبه تافه للكتابة (المخزن المؤقت STDOUT، قم بإرجاع سطر معين)، لكنني أريد معرفة ما إذا كان هناك بعض معيار أمر Shell للقيام بذلك سيكون متاحًا دون أن أقوم بإسقاط البرنامج النصي في مكانه.

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

المحلول

استخدام sed, ، للتنويع فقط:

ls -l | sed -n 2p

إن استخدام هذا البديل، والذي يبدو أكثر كفاءة لأنه يتوقف عن قراءة الإدخال عند طباعة السطر المطلوب، قد يؤدي إلى إنشاء SIGPIPE في عملية التغذية، والذي قد يؤدي بدوره إلى ظهور رسالة خطأ غير مرغوب فيها:

ls -l | sed -n -e '2{p;q}'

لقد رأيت ذلك كثيرًا لدرجة أنني عادةً ما أستخدم الأول (وهو أسهل في الكتابة على أي حال). ls ليس الأمر الذي يشكو عندما يحصل على SIGPIPE.

لمجموعة من الخطوط:

ls -l | sed -n 2,4p

لعدة نطاقات من الخطوط:

ls -l | sed -n -e 2,4p -e 20,30p
ls -l | sed -n -e '2,4p;20,30p'

نصائح أخرى

ls -l | head -2 | tail -1

بديل لطريقة الرأس/الذيل اللطيفة:

ls -al | awk 'NR==2'

أو

ls -al | sed -n '2p'

من sed1line:

# print line number 52
sed -n '52p'                 # method 1
sed '52!d'                   # method 2
sed '52q;d'                  # method 3, efficient on large files

من com.awk1line:

# print line number 52
awk 'NR==52'
awk 'NR==52 {print;exit}'          # more efficient on large files

من أجل الإنتهاء ؛-)

رمز أقصر

find / | awk NR==3

حياة أقصر

find / | awk 'NR==3 {print $0; exit}'

جرب هذا sed إصدار:

ls -l | sed '2 ! d'

تقول "احذف جميع الأسطر التي ليست السطر الثاني".

يمكنك استخدام اوك:

ls -l | awk 'NR==2'

تحديث

لن يحصل الكود أعلاه على ما نريده بسبب خطأ متتابع:ال ليرة سورية -ل السطر الأول للأمر هو المجموع خط.ومن أجل ذلك، سيعمل الكود المنقح التالي:

ls -l | awk 'NR==3'

هل لغة Perl متاحة لك بسهولة؟

$ perl -n -e 'if ($. == 7) { print; exit(0); }'

من الواضح أنه يمكنك استبدال الرقم الذي تريده بـ 7.

اقترح ملصق آخر

ls -l | head -2 | tail -1

ولكن إذا قمت بإدخال الرأس في الذيل، فيبدو أن كل شيء حتى السطر N تتم معالجته مرتين.

ذيل الأنابيب في الرأس

ls -l | tail -n +2 | head -n1

سيكون أكثر كفاءة؟

نعم، الطريقة الأكثر فعالية (كما أشار جوناثان ليفلر سابقًا) هي استخدام sed مع print & Quit :

set -o pipefail                        # cf. help set
time -p ls -l | sed -n -e '2{p;q;}'    # only print the second line & quit (on Mac OS X)
echo "$?: ${PIPESTATUS[*]}"            # cf. man bash | less -p 'PIPESTATUS'

همم

sed لم يعمل في حالتي.انا اقترح:

للخطوط "الفردية" 1،3،5،7 ...ls |awk '0 == (NR+1) % 2'

للخطوط "الزوجية" 2,4,6,8 ls |awk '0 == (NR) % 2'

لمزيد من الاكتمال..

ls -l | (for ((x=0;x<2;x++)) ; do read ; done ; head -n1)

تخلص من الأسطر حتى تصل إلى السطر الثاني، ثم اطبع السطر الأول بعد ذلك.لذلك، فإنه يطبع السطر الثالث.

لو كان السطر الثاني فقط..

ls -l | (read; head -n1)

ضع أكبر عدد ممكن من "القراءة" حسب الضرورة.

لقد أضفت هذا في ملفي .bash_profile

function gdf(){
  DELETE_FILE_PATH=$(git log --diff-filter=D --summary | grep delete | grep $1 | awk '{print $4}')
  SHA=$(git log --all -- $DELETE_FILE_PATH | grep commit | head -n 1 | awk '{print $2}')
  git show $SHA -- $DELETE_FILE_PATH
}

وهي تعمل

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