سؤال

لدي ملف .csv مثل هذا:

stack2@example.com,2009-11-27 01:05:47.893000000,example.net,127.0.0.1
overflow@example.com,2009-11-27 00:58:29.793000000,example.net,255.255.255.0
overflow@example.com,2009-11-27 00:58:29.646465785,example.net,256.255.255.0
...

لا بد لي من إزالة رسائل البريد الإلكتروني المكررة (الخط بأكمله) من الملف (أي واحدة من الخطوط التي تحتوي على overflow@example.com في المثال أعلاه). كيف يمكنني استخدام uniq في الحقل الوحيد 1 (مفصولة بفواصل)؟ بالنسبة الى man, uniq لا تملك خيارات للأعمدة.

حاولت شيئا مع sort | uniq لكنه لا يعمل.

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

المحلول

sort -u -t, -k1,1 file
  • -u لفريدة
  • -t, لذلك فاصلة هو محدد
  • -k1,1 للحقل الرئيسي 1

نتيجة الفحص:

overflow@domain2.com,2009-11-27 00:58:29.793000000,xx3.net,255.255.255.0 
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1 

نصائح أخرى

awk -F"," '!_[$1]++' file
  • -F يحدد فاصل الحقل.
  • $1 هو الحقل الأول.
  • _[val] انظر لفوق val في التجزئة _(متغير منتظم).
  • ++ زيادة، وإعادة القيمة القديمة.
  • ! إرجاع منطقي لا.
  • هناك طباعة ضمنية في النهاية.

للنظر في عمود متعددة.

فرز وإعطاء قائمة فريدة بناء على العمود 1 والعمود 3:

sort -u -t : -k 1,1 -k 3,3 test.txt
  • -t : القولون فاصل
  • -k 1,1 -k 3,3 بناء على العمود 1 والعمود 3

أو إذا كنت تريد استخدام UNIQUQ:

<mycvs.cvs tr -s ',' ' ' | awk '{print $3" "$2" "$1}' | uniq -c -f2

يعطي

1 01:05:47.893000000 2009-11-27 tack2@domain.com
2 00:58:29.793000000 2009-11-27 overflow@domain2.com
1

إذا كنت ترغب في الاحتفاظ بأخرى واحدة من التكرارات التي يمكنك استخدامها

 tac a.csv | sort -u -t, -r -k1,1 |tac

الذي كان متطلباتي

هنا

tac سوف عكس خط الملف حسب الخط

هنا هي طريقة أنيقة جدا.

قم أولا بتنسيق المحتوى بحيث يتم مقارنة العمود بالمقارنة مع التفرد عرضا ثابتا. طريقة واحدة للقيام بذلك هي استخدام OWK Printf مع محدد عرض حقل / عمود ("٪ 15s").

الآن يمكن استخدام خيارات -f و -w من UNIQ لتخطي الحقول / الأعمدة السابقة وتحديد عرض المقارنة (العمود (الأعمدة) العرض).

فيما يلي ثلاثة أمثلة.

في المثال الأول ...

1) جعل مؤقتا عمود الفائدة عرض ثابت أكبر من أو يساوي عرض الحقل الأقصى للحقل.

2) استخدام خيار uniq لتخطي الأعمدة السابقة واستخدام خيار -W UNIQ للحد من العرض إلى tmp_fixed_width.

3) إزالة المسافات الزائدة من العمود إلى "استعادة" عرضه (على افتراض أنه لم تكن هناك مساحات زائدة مسبقا).

printf "%s" "$str" \
| awk '{ tmp_fixed_width=15; uniq_col=8; w=tmp_fixed_width-length($uniq_col); for (i=0;i<w;i++) { $uniq_col=$uniq_col" "}; printf "%s\n", $0 }' \
| uniq -f 7 -w 15 \
| awk '{ uniq_col=8; gsub(/ */, "", $uniq_col); printf "%s\n", $0 }'

في المثال الثاني ...

قم بإنشاء عمود UNIQUQ جديد 1. ثم قم بإزالته بعد تطبيق فلتر UNIQ.

printf "%s" "$str" \
| awk '{ uniq_col_1=4; printf "%15s %s\n", uniq_col_1, $0 }' \
| uniq -f 0 -w 15 \
| awk '{ $1=""; gsub(/^ */, "", $0); printf "%s\n", $0 }'

المثال الثالث هو نفس الثانية، ولكن بالنسبة للأعمدة المتعددة.

printf "%s" "$str" \
| awk '{ uniq_col_1=4; uniq_col_2=8; printf "%5s %15s %s\n", uniq_col_1, uniq_col_2, $0 }' \
| uniq -f 0 -w 5 \
| uniq -f 1 -w 15 \
| awk '{ $1=$2=""; gsub(/^ */, "", $0); printf "%s\n", $0 }'

حسنا، أبسط أكثر من عزل العمود مع AWK، إذا كنت بحاجة إلى إزالة كل شيء بقيمة معينة لملف معين، فلماذا لا تفعل Grep فقط:

على سبيل المثال لحذف كل شيء بأقيمة "Col2" في الخط الثاني: Col1، Col2، Col3، Col4

grep -v ',col2,' file > file_minus_offending_lines

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

AWK لعزل العمود المخالف: على سبيل المثال

awk -F, '{print $2 "|" $line}'

تعدد -f تعيين الحقل المحدد إلى ""، "، 2 دولار يعني العمود 2، متبوعا ببعض محدد مخصص ثم السطر بأكمله. يمكنك بعد ذلك تصفية عن طريق إزالة الخطوط التي يبدأ مع القيمة المخالفة:

 awk -F, '{print $2 "|" $line}' | grep -v ^BAD_VALUE

ثم تجريد الأشياء قبل المحدد:

awk -F, '{print $2 "|" $line}' | grep -v ^BAD_VALUE | sed 's/.*|//g'

(ملاحظة - الأمر SED قذر لأنه لا يشمل القيم الهروب. كما يجب أن يكون نمط SED حقا شيء مثل [^ |] (أي أي شيء ليس الحلمين). ولكن نأمل أن يكون هذا واضحا بما فيه الكفاية.

عن طريق فرز الملف مع sort أولا، يمكنك التقديم بعد ذلك uniq.

يبدو أن فرز الملف جيد فقط:

$ cat test.csv
overflow@domain2.com,2009-11-27 00:58:29.793000000,xx3.net,255.255.255.0
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
overflow@domain2.com,2009-11-27 00:58:29.646465785,2x3.net,256.255.255.0 
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack3@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack4@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1

$ sort test.csv
overflow@domain2.com,2009-11-27 00:58:29.646465785,2x3.net,256.255.255.0 
overflow@domain2.com,2009-11-27 00:58:29.793000000,xx3.net,255.255.255.0
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack3@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack4@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1

$ sort test.csv | uniq
overflow@domain2.com,2009-11-27 00:58:29.646465785,2x3.net,256.255.255.0 
overflow@domain2.com,2009-11-27 00:58:29.793000000,xx3.net,255.255.255.0
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack3@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack4@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1

يمكنك أيضا القيام ببعض ماجيك AWK:

$ awk -F, '{ lines[$1] = $0 } END { for (l in lines) print lines[l] }' test.csv
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack4@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack3@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
overflow@domain2.com,2009-11-27 00:58:29.646465785,2x3.net,256.255.255.0 
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top