shell - نظام - جميع اوامر الاختراق kali linux
كيف يمكن أن أقوم بخلط خطوط ملف نصي على سطر أوامر Unix أو في برنامج نصي shell؟ (13)
أرغب في خلط أسطر الملف النصي بشكل عشوائي وإنشاء ملف جديد. قد يحتوي الملف على عدة آلاف من الأسطر.
كيف يمكنني أن أفعل ذلك مع القط ، awk ، قطع ، وما إلى ذلك؟
أستخدم نصًا برلوسًا صغيرًا ، أسميه "unsort":
#!/usr/bin/perl
use List::Util 'shuffle';
@list = <STDIN>;
print shuffle(@list);
لديّ أيضًا إصدارًا مفصولًا بـ NULL ، يُطلق عليه "unsort0" ... مفيد للاستخدام مع البحث عن -print0 وما إلى ذلك.
ملاحظة: صُوِّرت 'شوف' أيضًا ، لم يكن لدي أي فكرة عن وجودها في النواة هذه الأيام ... ما سبق قد يكون مفيدًا إذا لم يكن لديك نظام "شوف".
إذا كنت قد ركبت سكالا ، فإليك خطًا واحدًا لخلط الإدخال:
ls -1 | scala -e 'for (l <- util.Random.shuffle(io.Source.stdin.getLines.toList)) println(l)'
بطانة واحدة لبيثون تستند إلى إجابة scai ، ولكن أ) يأخذ stdin ، ب) يجعل النتيجة قابلة للتكرار مع البذور ، ج) يختار 200 فقط من جميع الخطوط.
$ cat file | python -c "import random, sys;
random.seed(100); print ''.join(random.sample(sys.stdin.readlines(), 200))," \
> 200lines.txt
بطانة واحدة للثعبان:
python -c "import random, sys; lines = open(sys.argv[1]).readlines(); random.shuffle(lines); print ''.join(lines)," myFile
ولطباعة خط عشوائي واحد فقط:
python -c "import random, sys; print random.choice(open(sys.argv[1]).readlines())," myFile
ولكن انظر هذا المنصب random.shuffle()
بيثون random.shuffle()
. random.shuffle()
. لن تعمل بشكل جيد مع العديد من العناصر (أكثر من 2080).
تتميز وظيفة bash هذه بالحد الأدنى من التبعية (فقط الفرز والبس):
shuf() {
while read -r x;do
echo $RANDOM$'\x1f'$x
done | sort |
while IFS=$'\x1f' read -r x y;do
echo $y
done
}
تكمل هذه الإجابة العديد من الإجابات الموجودة الكبيرة بالطرق التالية:
يتم حزم الإجابات الموجودة في وظائف shell مرنة :
- لا تأخذ الوظائف المدخلات
stdin
فقط ، ولكن بدلا من ذلك أيضا أسماء الملفات - تأخذ الوظائف خطوات إضافية للتعامل مع
SIGPIPE
بالطريقة المعتادة (الإنهاء الهادئ مع رمز الخروج141
) ، بدلاً من كسر الضوضاء. هذا مهم عند توجيه الإخراج الوظيفي إلى أنبوب مغلق في وقت مبكر ، كما هو الحال عند توجيه الأنبوب إلىhead
.
- لا تأخذ الوظائف المدخلات
يتم إجراء مقارنة الأداء .
- وظيفة متوافقة مع POSIX تعتمد على
awk
،sort
،cut
، مقتبسة من إجابة OP الخاصة :
shuf() { awk 'BEGIN {srand(); OFMT="%.17f"} {print rand(), $0}' "[email protected]" |
sort -k1,1n | cut -d ' ' -f2-; }
- بيرل الوظيفة القائمة - تكيفت من إجابة Moonyoung كانج :
shuf() { perl -MList::Util=shuffle -e 'print shuffle(<>);' "[email protected]"; }
- وظيفة تستند إلى بايثون ، مقتبسة من إجابة scai :
shuf() { python -c '
import sys, random, fileinput; from signal import signal, SIGPIPE, SIG_DFL;
signal(SIGPIPE, SIG_DFL); lines=[line for line in fileinput.input()];
random.shuffle(lines); sys.stdout.write("".join(lines))
' "[email protected]"; }
- دالة تستند إلى روبي ، مقتبسة من إجابة hoffmanc :
shuf() { ruby -e 'Signal.trap("SIGPIPE", "SYSTEM_DEFAULT");
puts ARGF.readlines.shuffle' "[email protected]"; }
مقارنة الأداء:
ملاحظة: تم الحصول على هذه الأرقام في جهاز iMac في أواخر عام 2012 باستخدام معالج Intel Core i5 بسرعة 3.2 جيجاهرتز وبرنامج Fusion Drive ، الذي يشغل OSX 10.10.3. في حين أن التوقيت يختلف مع نظام التشغيل المستخدم ، مواصفات الجهاز ، تطبيق awk
المستخدم (على سبيل المثال ، الإصدار awk
BSD المستخدم في OSX عادة ما يكون أبطأ من GNU awk
وخاصة mawk
) ، وهذا يجب أن يوفر إحساسًا عامًا بالأداء النسبي .
ملف الإدخال هو ملف بمليون خط يتم إنتاجه باستخدام seq -f 'line %.0f' 1000000
.
يتم سرد الأوقات بترتيب تصاعدي (الأسرع أولاً):
-
shuf
-
0.090s
-
- روبي 2.0.0
-
0.289s
-
- بيرل 5.18.2
-
0.589s
-
- الثعبان
-
1.342s
مع Python 2.7.6؛2.407s
(!) مع Python 3.4.2
-
-
awk
+sort
+cut
-
3.003s
مع BSDawk
؛2.388s
مع GNUawk
(4.1.1) ؛1.811s
withmawk
(1.3.4)؛
-
لمزيد من المقارنة ، فإن الحلول لا يتم تعبئتها كوظائف أعلاه:
-
sort -R
(ليس خلطًا حقيقيًا إذا كان هناك خطوط إدخال مكررة)-
10.661s
- يبدو أن تخصيص المزيد من الذاكرة لا يحدث فرقًا
-
- سكالا
-
24.229s
-
- حلقات
bash
+sort
-
32.593s
-
الاستنتاجات :
- استخدم
shuf
، إذا استطعت - إنه الأسرع حتى الآن. - روبي يفعل جيدا ، تليها بيرل .
- بايثون أبطأ بشكل ملحوظ من روبي و بيرل ، و بمقارنة إصدارات بايثون ، 2.7.6 هي أسرع قليلا من 3.4.1
- استخدم مجموعة التحرير
awk
+sort
+ المتوافق مع POSIX كملاذ أخير ؛ التي تستخدم فيها تطبيقawk
(mawk
أسرع من GNUawk
، BSDawk
هي الأبطأ). - البقاء بعيدا عن
sort -R
،bash
الحلقات ، سكالا.
شكل awk
آخر:
#!/usr/bin/awk -f
# usage:
# awk -f randomize_lines.awk lines.txt
# usage after "chmod +x randomize_lines.awk":
# randomize_lines.awk lines.txt
BEGIN {
FS = "\n";
srand();
}
{
lines[ rand()] = $0;
}
END {
for( k in lines ){
print lines[k];
}
}
في ما يلي أول محاولة سهلة على المبرمج ولكن من الصعب على وحدة المعالجة المركزية (CPU) التي تضيف رقمًا عشوائيًا لكل سطر ، وتقوم بفرزها ثم تسقط الرقم العشوائي من كل سطر. في الواقع ، يتم فرز الخطوط بشكل عشوائي:
cat myfile | awk 'BEGIN{srand();}{print rand()"\t"$0}' | sort -k1 -n | cut -f2- > myfile.shuffled
لدينا مجموعة للقيام بهذه المهمة:
sudo apt-get install randomize-lines
مثال:
إنشاء قائمة مرتبة من الأرقام وحفظها على 1000.txt:
seq 1000 > 1000.txt
لخلطها ، ببساطة استخدام
rl 1000.txt
لم يرد ذكره بعد:
استخدام
unsort
. بناء الجملة (موجهة إلى حد ما قائمة التشغيل):unsort [-hvrpncmMsz0l] [--help] [--version] [--random] [--heuristic] [--identity] [--filenames[=profile]] [--separator sep] [--concatenate] [--merge] [--merge-random] [--seed integer] [--zero-terminated] [--null] [--linefeed] [file ...]
يمكن أن
msort
، ولكن عادة ما يكون overkill:seq 10 | msort -jq -b -l -n 1 -c r
وظيفة بسيطة مبنية على awk ستقوم بهذه المهمة:
shuffle() {
awk 'BEGIN{srand();} {printf "%06d %s\n", rand()*1000000, $0;}' | sort -n | cut -c8-
}
الاستعمال:
any_command | shuffle
يجب أن يعمل هذا على أي UNIX تقريبًا. تم اختباره على Linux و Solaris و HP-UX.
تحديث:
لاحظ أن %06d
الأصفار البادئة ( %06d
) و rand()
تجعلها تعمل بشكل صحيح أيضًا على أنظمة لا يفهم فيها sort
الأرقام. ويمكن فرزها عن طريق النظام المعجمى (المعروف أيضا باسم مقارنة السلسلة العادية).
وهنا سكربت awk
awk 'BEGIN{srand() }
{ lines[++d]=$0 }
END{
while (1){
if (e==d) {break}
RANDOM = int(1 + rand() * d)
if ( RANDOM in lines ){
print lines[RANDOM]
delete lines[RANDOM]
++e
}
}
}' file
انتاج
$ cat file
1
2
3
4
5
6
7
8
9
10
$ ./shell.sh
7
5
10
9
6
8
2
1
3
4
يمكنك استخدام shuf
. على بعض الأنظمة على الأقل (لا يبدو أن في POSIX).
كما أشار جليفديف: قد يكون sort -R
خيارًا أيضًا. على بعض النظم على الأقل ؛ حسنا ، يمكنك الحصول على الصورة. وقد أشير إلى أن هذا sort -R
لا sort -R
الواقع ، ولكن بدلا من ذلك فرز العناصر وفقا لقيمة التجزئة الخاصة بهم.
[ملاحظة المحرر: sort -R
تقريبًا تقريبًا ، باستثناء أن الأسطر المكررة / مفاتيح الفرز تنتهي دائمًا بجانب بعضها البعض . وبعبارة أخرى: فقط مع خطوط الإدخال / المفاتيح فريدة من نوعها هو أنه خلط ورق اللعب الحقيقي. في حين أنه صحيح أن يتم تحديد ترتيب الإخراج بواسطة قيم التجزئة ، تأتي العشوائية من اختيار دالة تجزئة عشوائية - راجع manual .]