الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

حساب عدد الكلمات المختلفة

بدأه To HigH في 13 مارس 2014 · 18 رد · 1,360 مشاهدة · في نظام تشغيل Unix & Linux
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ورحمة الله وبركاته

 

 

مشكلتي أن لدي مجموعة كبيرة من الملفات العربية النصية الطويلة، وأريد حساب جميع الكلمات المختلفة في كل الملفات.

مثلاً لتتضح الصورة، ليكن لدي ثلاث ملفات تحتوي على التوالي:

1- بسم الله الرحمن الرحيم.2- سبحان الله.3- سبحانه وتعالى  .

فالمخرج يجب أن يكون: 7.

 

بعد البحث في أوامر Unix لم أجد المطلوب. ماوجدته كان يتعلق مثلاً بأوامر wc و grep وهما لايعطيان المطلوب.

 

فهل ممكن ويوجد أوامر في أنظمة Unix تقوم بهذه المهمة؟

 

 

وجزاكم الله خيراً

#2

وعليك السلام ورحمة الله وبركاته

 

الأمر wc يقوم بالمهمة بشكل صحيح وتام

إليك هذا السكريبت الذي كتبته لك

#!/usr/bin/bash
FILES=~/path/*
count=0
for i in $FILES 
do
  while read line; do 
    count=$((count+ $(echo $line | wc -w))) 
  done < $i
done
echo $count

ضعي ملفاتك في مجلد اسمه path واجعله في home

تم تعديل هذه المشاركة بواسطة أحمد أبو عبد البر في 15 مارس 2014 في 22:40

1

vVIfFr.gif

مدونتي



إذا رأيتموني غبت فأطلت الغياب فربما أكون قد انتقلت عن الدنيا إلى الآخرة

فما أحوجني إلى دعوة صالحة من أخ لي كريم

 

http://www.tvquran.com/

 

LoGeCom

أول برنامج عربي للمحاسبة والتجارة وإدراة المخازن يعمل على اللينكس والماك والويندوز 

#3

جزاك الله خيراً على مساعدتك

 

قمت بتجريب السكربيت على مجموعة تجريبية من الملفات النصية مرة باللغة الإنجليزية ومرة بالعربية.

ولكن في كلا الحالتين يقوم بعد المجموع الكلي للكلمات. بغض النظر سواء تكررت الكلمة أم لم تتكرر.

أما كنت أريده هو عد الكلمات المختلفة فقط بدون عد التكرارات.

 

 

وكذلك يوجد مشكلة آخرى.

عندما أنشئ مجلد path وأضع به الملفات التجريبية وأجري تطبيق السكربت يتم العمل كما هو متوقع (عد جميع الكلمات سواء مكررة أم لا).

وعندما أحاول تغير محتوى تلك الملفات بزيادة كلمات أو حذفها  لاينتج العدد كما هو متوقع، بل يكون أكثر.

وكأن العداد الموجود في السكربت لايعود القيمة لـ0 عند بداية العد بل يضيف على القيمة السابقة.

count=0

ويكون الحل هو حذف المجلد وأضافته من جديد فيعود العمل الطبيعي.

مثلاً:

لدي ملفين كل واحد منهما به الكلمة نفسها, فالمجموع الناتج هو: 2.

وعندما أحرر أحد الملفين وأضيف له كلمة آخرى ينتج: 4 (وكان من المفترض أن يكون3).

وعند حذف المجلد وإضافة ملفين أحدهما به كلمتين والآخر كلمة واحدة ينتج العدد: 3.

 

وأخيراً أقول جزاك الله خيراً على اقتطاع جزء من وقتك لمساعدتي.

شكراً جزبلاً

#4

وعليكم السلام ورحمة الله وبركاته،

 

قد يحقق لك uniq مرادك:

cat file1 file2 file3 file... | tr ' ' '\n' | uniq | wc -w

uniq لا يطبع السطور إلا مرة واحدة. ويتجاهل السطور المكررة. استخدمت tr لتحويل المسافات إلى نهايات السطور.

تم تعديل هذه المشاركة بواسطة سليمان الإبراهيم في 16 مارس 2014 في 11:42

1
#5

جزاك الله خيراً أخ سليمان.

 

ولكن ألتمس العذر منك لكوني لست خبيرة في نظام اللينكس.

هل تقصد أن أعدد بعد أمر cat جميع الملفات التي أحتاج عدها؟

 

أم تقصد أن من الممكن أن يكون السكربت هكذا؟ حاولت تجربته كالسكربت التالي ولم يفلح.

#!/usr/bin/bash
FILES=~/path/*
count=0
for i in $FILES 
do
  while read line; do 
    count=$((count+ $(echo $line | tr ' ' '\n' | uniq | wc -w))) 
  done < $i
done
echo $count

تم تعديل هذه المشاركة بواسطة To HigH في 16 مارس 2014 في 12:23

#6
اقتباس

 

هل تقصد أن أعدد بعد أمر cat جميع الملفات التي أحتاج عدها؟

 

نعم. إذا قلنا أن لديك 3 ملفات:

‎/tmp/a.txt‎

‎/tmp/b.txt‎

‎/tmp/c.txt‎

 

فإن الأمر المستخدم هو:

cat /tmp/a.txt /tmp/b.txt /tmp/c.txt | tr ' ' '\n' | uniq | wc -w

أو اذا احتوى دليل (مجلد)  /tmp/my_files/  على الملفات، فإن الأمر سيكون

cat /tmp/my_files/* | tr ' ' '\n' | uniq | wc -w

ولا تحتاجين السكربت في هذه الحالة.

1
#7

قمت بتجربته لكلا اللغتين العربية والأنجليزية. وللأسفلم يجدي.

 

بالفعل هو لا يقوم بإظهار المجموع الكلي، وفي نفس الوقت لايظهر  فقط عدد الكلمات المختلفة.

 

حتى عند تغيير ترتيب  الكلمات في الملف يعتبرها كلمة مختلفة، وعند إدراج مسافة يعتبرها أيضاً كلمة آخرى مع أننا في الأمر جعلنا كل مسافة تعتبر كانها نهاية سطر.

 

مثلاً استخدمت كلمتين فقط في 10 ملفات في كل مرة اغير الترتيب أو أبقي على كلمة واحدة فقط أو أضيف المسافات.

وفي الناتج خرج لي: 11

 

 

 

 

--------------------

تحديث/

 

وجدت هذا الأمر لطلب مشابه حيث يكون المخرجات طباعة الكلمات المختلفة فقط من ملف واحد:

awk '{a[$1]} END {for(i in a) print i}' filename

فعند تجربته فهو يطبع أول كلمة من كل سطر فقط.

وبالتالي عند تغيير المجال من ملف إلى مجلد فإنه يطبع بعض الكلمات الموجودة في الملفات وليست كل الكلمات.

 

 

وعند محاولتي لجعل هذا الأمر يتنفذ على كل ملف بالاستفادة من السكربت السابق هكذا:

#!/usr/bin/bash
FILES=~/path/*

count=0
for j in $FILES 
do
      count=$((count+ $(echo awk '{a[$1]} END {for(i in a) print i}' j))) 
done
echo $count

تظهر مشكلة في عملية الجمع:

arithmetic expression: expecting EOF: "count+ awk {a[$1]} END {for(i in a) print i} j"

تم تعديل هذه المشاركة بواسطة To HigH في 16 مارس 2014 في 15:02

#8

طريقة الأخ سليمان جميلة ولكن تنقصها ترتيب الأسطر لأن الامر uniq لا يعمل إلا في الأسطر المرتبة ولذلك أضفت أمر الترتيب إلى جملته فصات هكذا

cat ~/path/* | tr ' ' '\n' | sort | uniq | wc -w

تم تعديل هذه المشاركة بواسطة أحمد أبو عبد البر في 16 مارس 2014 في 16:55

2

vVIfFr.gif

مدونتي



إذا رأيتموني غبت فأطلت الغياب فربما أكون قد انتقلت عن الدنيا إلى الآخرة

فما أحوجني إلى دعوة صالحة من أخ لي كريم

 

http://www.tvquran.com/

 

LoGeCom

أول برنامج عربي للمحاسبة والتجارة وإدراة المخازن يعمل على اللينكس والماك والويندوز 

#9

مشكورين جداً أخ أحمد وأخ سليمان.

 

قمت بتطبيقه على اللغة الإنجليزية كالتالي وتم بشكل رائع:

cat ~/path/* | tr ' ' '\n' |tr -cd 'a-zA-Z''\n'| sort | uniq | wc -w

أضفت الأمر tr مرة آخرى للتحكم وجعل الكلمات ذات الحروف الأبجدية فقط هي التي تكون داخلة ضمن العد. أرجو أن تكون كتابتي منطقية.

 

 

 

وعندما حاولت تطبيقه على اللغة العربية وأبدلت الأحرف بالأحرف العربية:

cat ~/path/* | tr ' ' '\n' |tr -cd 'بتثجحخدذرزسشصضطظعغفقكلمنهويا''\n'| sort | uniq | wc -w

واستخدمت ملفات من نوع ترميز "windows 1256" لم يتعرف عليها، بل يخرج الناتج: 0

 

الملفات أنشأتها عن طريق فتح برنامج OpenOffice Writer
وعمل "حفظ باسم" وعندما يسأل عن الترميز  اختار ترميز Windows-1256 .

 

ولكن عندما أفتح الملف في متصفح الانترنت لأرى نوع ترميز الملف لا يظهر التحديد على Windows-1256.

الملفات عندما أفتحها كمستند أستطيع قرائتها "لتفعيلي للترميز العربي" ولكن شكلها الخارج يوحي وكأنها غير معرفة كالصورة:

http://im85.gulfup.com/vfXPo.tiff

 

أما عندما أجعل ترميز الملف الترميز الافتراضي للمستند فهو يقوم بالعملية ويجمع الكلمات المختلفة بطريقة صحيحة. وأيقونة المستند تظهر الكلمات من خلالها بشكل سليم.

 

فالخطأ هنا من عدم تعرفه على ترميز "windows 1256" وهو الترميز الذي أريده.

فهل المشكلة في طريقة حفظي أم في إعدادت النظام؟

#10
اقتباس

 

 

فهل المشكلة في طريقة حفظي أم في إعدادت النظام؟

أنت حفظت الملف بترميز win-1256 ولكن ترميز التاريمنال حيث نفذت الأمر هو الافتراضي UTF−8

يجب أن يكون توافق في الترميز

 

وأظن أنه لا داعي إلى استعمال ترميز win-1256 لأن الافتراضي يفي بالغرض

1

vVIfFr.gif

مدونتي



إذا رأيتموني غبت فأطلت الغياب فربما أكون قد انتقلت عن الدنيا إلى الآخرة

فما أحوجني إلى دعوة صالحة من أخ لي كريم

 

http://www.tvquran.com/

 

LoGeCom

أول برنامج عربي للمحاسبة والتجارة وإدراة المخازن يعمل على اللينكس والماك والويندوز 

#11
أحمد أبو عبد البر كتب:

وأظن أنه لا داعي إلى استعمال ترميز win-1256 لأن الافتراضي يفي بالغرض

 

ولكن العمل يستلزم استخدام ترميز win-1256

 

 

 

 

أحمد أبو عبد البر كتب:

أنت حفظت الملف بترميز win-1256 ولكن ترميز التاريمنال حيث نفذت الأمر هو الافتراضي UTF−8

يجب أن يكون توافق في الترميز

 

 

فجربت هذا الأمر للتغير أحد الملفات:

iconv --to-code=WINDOWS-1256 path/1.txt > path/out.txt

والنتيجة كما في الرد السابق، لم تتغير شكل الأيقونة ولم تتعرف الطرفية على أي كلمة، وأيضا الترميز الذي يعرضه المتصفح western (wind-1252)

 

 

 

أما الطرفية فهي تقرأ اللغة العربية من اليمين لليسار بشكل صحيح بعد أن استخدمت الأمر:

sudo apt-get install libfribidi0 libfribidi-dev

وتحميل برنامح: Bidirectional Console

ثم تعديل الملف النصي الخاص بإعدادات الطرفية، ليفتح من النسخة الداعمة للغة العربية باستخدام الأمر التالي

sudo gedit /usr/share/applications/gnome-terminal.desktop

ثم إضافة السطرين التالية له:

Terminal=trueExec=/usr/bin/bicon.bin

ومازالت المشكلة لم يتعرف على الكلمات.

تم تعديل هذه المشاركة بواسطة To HigH في 17 مارس 2014 في 11:09

#12

بقي عليك أن تغيري encodage of terminal 

نفذي الأمر التالي

gconftool --set --type=string /apps/gnome-terminal/profiles/Default/encoding WINDOWS-1256

vVIfFr.gif

مدونتي



إذا رأيتموني غبت فأطلت الغياب فربما أكون قد انتقلت عن الدنيا إلى الآخرة

فما أحوجني إلى دعوة صالحة من أخ لي كريم

 

http://www.tvquran.com/

 

LoGeCom

أول برنامج عربي للمحاسبة والتجارة وإدراة المخازن يعمل على اللينكس والماك والويندوز 

#13
أحمد أبو عبد البر كتب:

 

بقي عليك أن تغيري encodage of terminal 

نفذي الأمر التالي

gconftool --set --type=string /apps/gnome-terminal/profiles/Default/encoding WINDOWS-1256

 

نفذته ومازالت المشكلة. وأيضاً الحروف العربية تظهر للشاشة ومعها بعض الرموز الآخرى.

 

 

وحتى عندما أعمل

$ reset

ثم أذهب إلى القائمة وأختار:

Terminal->Set Character Encoding->WINDOWS-1256

تكون كسابقتها لم تتغير النتيجة.

 

 

 

 

وعندما أنفذ الأمر التالي لعرض نوع الترميز يظهر مساحة فارغة:

$ echo $LC_CTYPE

وهذا الأمر التالي لعرض اللغة يخرج هكذا:

echo $LANGen_US.UTF-8

وعندما أنفذ الأمر التالي لعرض اللغات لاتظهر العربية من بينها:

$ locale -a

وعندما  أنفذ الأمر التالي لإظهار الترميز الحالي يكون:

$ locale charmapUTF-8

وعندما أنفذ الأمر التالي لعرض الترميزات المتاحة يظهر مجموعة من ضمنها هذا الترميز:

$ locale -mCP1256

فقمت بتعديل  الأومر السابقة للترميز السابق كهذا:

$ gconftool --set --type=string /apps/gnome-terminal/profiles/Default/encoding CP1256
$ iconv --to-code=CP1256 path/1.txt > path/out.txt

ومازالت المشكلة قائمة حتى الآن.

تم تعديل هذه المشاركة بواسطة To HigH في 18 مارس 2014 في 11:56

#14

حقيقة لا أعرف ما سبب المسكلة بشأن الترميز

ولكن الأكيد أن المشكلة في الأمر wc إذا لا يتعامل مع الترميز cp-1256

على كل حال غيري الخاصية -w إلى الخاصية -l

ليصير الأمر هكذا

...| wc -l

vVIfFr.gif

مدونتي



إذا رأيتموني غبت فأطلت الغياب فربما أكون قد انتقلت عن الدنيا إلى الآخرة

فما أحوجني إلى دعوة صالحة من أخ لي كريم

 

http://www.tvquran.com/

 

LoGeCom

أول برنامج عربي للمحاسبة والتجارة وإدراة المخازن يعمل على اللينكس والماك والويندوز 

#15
أحمد أبو عبد البر كتب:

 

ولكن الأكيد أن المشكلة في الأمر wc إذا لا يتعامل مع الترميز cp-1256

على كل حال غيري الخاصية -w إلى الخاصية -l

ليصير الأمر هكذا

...| wc -l

 

 

جزاك الله خيرا أخ أحمد. بالفعل بعد التغير أصبحت الطرفية تتعرف على الكلمات.

ولكن للأسف لاتعطي نتجية صحيحة.

هل يمكن أن يكون السبب هو بعد أمر تغيير ترميز الطرفية؟ لأن من بعد أن قمت بتغير الترميز لم تعد تظهر الحروف الحروف كما هي بالترتيب والشكل السابق .

 

قمت بتغير الإعدادات كالتالي: فزالت مشكلة ظهور الأحرف، ولكن عدد الكلمات لم يكن دقيقاً.

 

Terminal -> Reset

Terminal->Set Character Encoding->Current Locale (UTF-8)

OR Terminal->Set Character Encoding->Unicode (UTF-8)

 

 

 

أحمد أبو عبد البر كتب:

 

ولكن الأكيد أن المشكلة في الأمر wc إذا لا يتعامل مع الترميز cp-1256

 

امم فهل من الممكن الاستغناء عن الأمر wc ليكون مثلاً كالتالي:

tr -cs 'بتثجحخدذرزسشصضطظعغفقكلمنهويا' '\n'|  sort | uniq  <~/path/*

ولكن تخرج لي مشكلة

 

~/ path/*: ambiguous redirect

ولما أضع اسم الملف بين علامات تنصيص كهذه "" أو هذه '' يخرج مشكلة أن اسم الملف غير موجود.

 

 

جزاك الله خيراً أخ أحمد على محاولاتك وبذلك لوقتك وجهدك في محاولة حل المشكلة, جعله الله في ميزان حسناتك.

تم تعديل هذه المشاركة بواسطة To HigH في 19 مارس 2014 في 19:50

#16

ما هو الفارق

 

ثم استخدمي هذا الأمر البسيط بدون تحديد أحرف الهجاء العربية ما دامت الملفات عربية

cat path/* | tr ' ' '\n' | sort | uniq | wc -l

vVIfFr.gif

مدونتي



إذا رأيتموني غبت فأطلت الغياب فربما أكون قد انتقلت عن الدنيا إلى الآخرة

فما أحوجني إلى دعوة صالحة من أخ لي كريم

 

http://www.tvquran.com/

 

LoGeCom

أول برنامج عربي للمحاسبة والتجارة وإدراة المخازن يعمل على اللينكس والماك والويندوز 

#17
أحمد أبو عبد البر كتب:

 

ما هو الفارق

 

ثم استخدمي هذا الأمر البسيط بدون تحديد أحرف الهجاء العربية ما دامت الملفات عربية

cat path/* | tr ' ' '\n' | sort | uniq | wc -l

الملفات عربية لكنها قد تحتوي على رموز أو أرقام قد تزيد عدد الكلمات، وأنا أريد عدد الكلمات الفعلية فقط 

#18

الخطأ هو خطأ في التعرف على بعض الكلمات.

لأتأكد من الأمر جعلت الناتج يخرج في ملف لأرى ماهي القيم التي قام بحسابها بشكل خاطئ عند تطبيق الأمر wc -l.

 

مثلاً كانت 3 ملفات على التوالي

سبحانه الله1 وبحمدهالله أكبر .الرحمن 1 2 3 4 5 6 7
بسم الله الرحمن الرحيم  8 9 10
سبحان الله وبحمدهسبحانه.

فكانت نتيجة هذا الأمر:

cat ~/path/*.txt | tr ' ' '\n' |tr -cd 'ا...ي''\n'| sort | uniq -c > path.out/out.txt

هو:

16 1 بسم5 الله1 سبحان7 الرحمن

بحيث:  قام بحساب عدد السطور الفارغة وجميع الرموز التي ليست أحرف كلكمة

(لكن لايهم سأقوم في النهاية بطرح الرقم 1 من المجموع الكلي)

 

لكن المشكلة هو في الكلمات التي استخرجها.

  • تعرف على عدد الكلمات فعلياً  فالعدد الكلي للكلمات هو 14 وهو العدد الفعلي الموجود.
  • لكن طريقة قرائتها خاطئة. حيث اعتبر مثلاً كلمة "الله" ظهرت 5 مرات بينما في الوقع 4 مرات فقط.
  • وتجاهل وجود كلمة "سبحانه" بينما حروفها مثلاً ظاهرة في كلمات آخرى قد تعرف عليها كـ "الله" و"سبحان"
#19

الحمدلله تم حل المشكلة.

 

استخدمت الأمرين التاليين:

cat ~/path/*.txt | tr ' ' '\n' |tr -cd 'ا...ي''\n'| awk '{a[$1]} END {for(i in a) print i}'  > path.out/out.txt 
awk 'END {print NR}' ~/path.out/out.txt

قمت بتجربتها على عينة ونجحت. أتمنى أن تخرج بنتيجة صجيجة عند تطبيقها على جميع الملفات.

أعتذر عن الإزعاج واستهلاك وقتكم جميعاً. جزاكم الله خيراً.

 

 

ولكن هل ممن الممكن طباعة عدد الأسطر مباشرة بدون الحاجة لتخرين الملف؟

مازلت أحاول أن أجد حل لها ﻷانني أخشى عندما تزيد عدد الأسطر على مئات الآلاف فتنتج مشكلة آخرى.

مواضيع مشابهة