Команды Awk или Sed для удаления дубликатов из файла CSV - PullRequest
1 голос
/ 31 марта 2020

У меня есть сгенерированный файл CSV, который содержит дубликаты значений. Я хотел бы удалить / удалить эти дубликаты значений с помощью команд AWK или Sed.

Фактический вывод

10.135.83.48,9042
10.135.83.46,9042
10.135.83.44,9042
10.5.197.25,10334
10.39.8.166,1500
10.135.83.48,9042
10.135.83.46,9042
10.135.83.44,9042
https://t-mobile.com,443
https://t-mobile.com,443
http://localhost:5059/abc/token,80

Ожидается вывод

  10.135.83.48,9042
    10.135.83.46,9042
    10.135.83.44,9042
    10.5.197.25,10334
    10.39.8.166,1500
https://t-mobile.com,443
http://localhost:5059/abc/token,80

Из нескольких файлов свойств я получил этот вывод. Ниже приведен скрипт, который я пытаюсь

#!/bin/bash
for file in $(ls); 
do 
#echo  " --$file -- "; 
grep -P  '((?<=[^0-9.]|^)[1-9][0-9]{0,2}(\.([0-9]{0,3})){3}(?=[^0-9.]|$)|(http|ftp|https|ftps|sftp)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/+#-]*[\w@?^=%&/+#-])?|\.port|\.host|contact-points|\.uri|\.endpoint)' $file|grep '^[^#]' |awk '{split($0,a,"#"); print a[1]}'|awk '{split($0,a,"="); print a[1],a[2]}'|sed 's/^\|#/,/g'|awk '/http:\/\//  {print $2,80}
       /https:\/\// {print $2,443}
       /Points/     {print $2,"9042"}
       /host/       {h=$2}
       /port/       {print h,$2; h=""}'|awk -F'[, ]' '{for(i=1;i<NF;i++){print $i,$NF}}'|awk 'BEGIN{OFS=","} {$1=$1} 1'|sed '/^[0-9]*$/d'|awk -F, '$1 != $2' 
done |awk '!a[$0]++' 
#echo "Done."
stty echo
cd ..

awk '! A [$ 0] ++' -> Это команда, которую я пытаюсь объединить с приведенным выше скриптом. По отдельности эта команда работает. Но когда я пытаюсь совместить ее с вышеуказанным сценарием, она не работает должным образом.

Заранее спасибо за помощь.

Ответы [ 3 ]

1 голос
/ 31 марта 2020

Самый простой способ приблизиться к этому (или один из самых простых) состоит в том, чтобы сохранить массив индексированным по записям, которые были замечены. Если записи отсутствуют в массиве seen, добавьте их и распечатайте запись. Если это так, просто пропустите запись, например,

awk '$0 in seen{next}; {seen[$0]++}1' file

Пример использования / Вывод

При вводе в файл с именем dupes вы получите:

$ awk '$0 in seen{next}; {seen[$0]++}1' dupes
10.135.83.48,9042
10.135.83.46,9042
10.135.83.44,9042
10.5.197.25,10334
10.39.8.166,1500
https://t-mobile.com,443
http://localhost:5059/abc/token,80
1 голос
/ 31 марта 2020

Это может сработать для вас (GNU sed):

sed -E 'H;x;s/((\n[^\n]+)(\n.*)*)\2$/\1/;x;$!d;x;s/.//' file1

Добавить текущую строку к пробелу удержания (HS) и, если она дублируется, удалить ее.

В конце файла переключитесь на HS, удалите первый символ (который является артефактом новой строки) и напечатайте результат.

NB При этом удаляются дубликаты, но сохраняется первоначальный порядок.

1 голос
/ 31 марта 2020

Попробуйте

#!/bin/bash
for file in *; 
do 
#echo  " --$file -- "; 
grep -P  '((?<=[^0-9.]|^)[1-9][0-9]{0,2}(\.([0-9]{0,3})){3}(?=[^0-9.]|$)|(http|ftp|https|ftps|sftp)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/+#-]*[\w@?^=%&/+#-])?|\.port|\.host|contact-points|\.uri|\.endpoint)' $file|grep '^[^#]' |awk '{split($0,a,"#"); print a[1]}'|awk '{split($0,a,"="); print a[1],a[2]}'|sed 's/^\|#/,/g'|awk '/http:\/\//  {print $2,80}
       /https:\/\// {print $2,443}
       /Points/     {print $2,"9042"}
       /host/       {h=$2}
       /port/       {print h,$2; h=""}'|awk -F'[, ]' '{for(i=1;i<NF;i++){print $i,$NF}}'|awk 'BEGIN{OFS=","} {$1=$1} 1'|sed '/^[0-9]*$/d'|awk -F, '$1 != $2' | awk '!a[$0]++'  
done 
#echo "Done."
stty echo
cd ..
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...