حدد قيمًا فريدة أو مميزة من قائمة في برنامج UNIX Shell النصي
سؤال
لدي برنامج نصي ksh يُرجع قائمة طويلة من القيم، مفصولة بسطر جديد، وأريد رؤية القيم الفريدة/المتميزة فقط.فمن الممكن أن تفعل هذا؟
على سبيل المثال، لنفترض أن الإخراج الخاص بي هو لاحقات الملفات في الدليل:
tar gz java gz java tar class class
أريد أن أرى قائمة مثل:
tar gz java class
المحلول
قد ترغب في إلقاء نظرة على uniq
و sort
التطبيقات.
./yourscript.ksh | sort | uniq
(لمعلوماتك، نعم، هذا النوع ضروري في سطر الأوامر هذا، uniq
يقوم فقط بإزالة الخطوط المكررة التي تقع مباشرة بعد بعضها البعض)
يحرر:
خلافا لما نشره آرون ديجولا المتعلق ب uniq
خيارات سطر الأوامر:
نظرا للمدخلات التالية:
class jar jar jar bin bin java
uniq
سيتم إخراج جميع الأسطر مرة واحدة بالضبط:
class jar bin java
uniq -d
سوف يقوم بإخراج كافة الأسطر التي تظهر أكثر من مرة، وسوف يقوم بطباعتها مرة واحدة:
jar bin
uniq -u
سوف يقوم بإخراج كافة الأسطر التي تظهر مرة واحدة بالضبط، وسوف يقوم بطباعتها مرة واحدة:
class java
نصائح أخرى
./script.sh | sort -u
وهذا هو نفس أول أكسيد ل<لأ href = "https://stackoverflow.com/questions/618378/ حدد فريد-أو-متميزة القيم من واحد في القائمة في ويونكس قذيفة النصي / 618381 # 618381 "> الجواب ، ولكن قليلا أكثر إيجازا.
لمجموعات البيانات الكبيرة حيث الفرز قد لا يكون مرغوبا فيه، يمكنك أيضا استخدام البرنامج النصي بيرل التالية:
./yourscript.ksh | perl -ne 'if (!defined $x{$_}) { print $_; $x{$_} = 1; }'
وهذا في الأساس مجرد يتذكر كل خط الانتاج بحيث لا إخراجه مرة أخرى.
ولديها ميزة على حل "sort | uniq
" في أنه لا يوجد الفرز المطلوبة في خط الهجوم.
مع zsh م> يمكنك القيام بذلك:
zsh-5.0.0[t]% cat infile
tar
more than one word
gz
java
gz
java
tar
class
class
zsh-5.0.0[t]% print -l "${(fu)$(<infile)}"
tar
more than one word
gz
java
class
وأو يمكنك استخدام AWK:
zsh-4.3.9[t]% awk '!_[$0]++' infile
tar
more than one word
gz
java
class
والأنابيب من خلال sort
وuniq
. هذا يزيل كل التكرارات.
وuniq -d
يعطي فقط التكرارات، uniq -u
يعطي فقط تلك فريدة (يجرد مكررة).
ومع AWK يمكنك القيام به، أجد أنه أسرع من نوع
./yourscript.ksh | awk '!a[$0]++'
وفريدة من نوعها، كما طلب منها، (ولكن غير مصنفة)؛
يستخدم موارد النظام أقل أقل من ~ 70 عنصرا (كما تم اختبارها مع مرور الوقت)؛
كتب لاتخاذ مدخلات من ستدين،
(أو تعديل وتدرج في نص برمجي آخر):
(باش)
bag2set () {
# Reduce a_bag to a_set.
local -i i j n=${#a_bag[@]}
for ((i=0; i < n; i++)); do
if [[ -n ${a_bag[i]} ]]; then
a_set[i]=${a_bag[i]}
a_bag[i]=$'\0'
for ((j=i+1; j < n; j++)); do
[[ ${a_set[i]} == ${a_bag[j]} ]] && a_bag[j]=$'\0'
done
fi
done
}
declare -a a_bag=() a_set=()
stdin="$(</dev/stdin)"
declare -i i=0
for e in $stdin; do
a_bag[i]=$e
i=$i+1
done
bag2set
echo "${a_set[@]}"