2010-06-21 2 views
1

Люди,Каков наилучший способ удаления повторных строк из файла в Bash?

У меня есть файл, содержащий записи ldap, и я хочу удалить строки «version: 1» из второго вхождения и включения. Я знаю, что sed может делать такие вещи, но так как я очень новичок, я не знаю, как это сделать. Это Solaris 10 машины и файл выглядит следующим образом:

version: 1 
dn: uid=tuser1,ou=people,o=example.com,o=isp 
cn: tuser1 
uidNumber: 3 
gidNumber: 3 
homeDirectory: /export/home/tuser1 
loginShell: /bin/sh 
objectClass: posixAccount 
objectClass: shadowAccount 
objectClass: account 
objectClass: top 
uid: tuser1 
shadowLastChange: 
userPassword: 

version: 1 
dn: uid=tuser2,ou=people,o=example.com,o=isp 
uidNumber: 20 
cn: tuser1 
gidNumber: 3 
homeDirectory: /export/home/tuser2 
loginShell: /bin/sh 
objectClass: posixAccount 
objectClass: shadowAccount 
objectClass: account 
objectClass: top 
uid: tuser1 
shadowLastChange: 
userPassword: 

version: 1 
dn: uid=tuser3,ou=people,o=example.com,o=isp 
uidNumber: 10 
cn: tuser3 
gidNumber: 3 
homeDirectory: /export/home/tuser3 
loginShell: /bin/sh 
objectClass: posixAccount 
objectClass: shadowAccount 
objectClass: account 
objectClass: top 
uid: tuser3 
shadowLastChange: 
userPassword: 

version: 1 
dn: uid=loperp,ou=people,o=example.com,o=isp 
uid: loperp 
userPassword: 
objectClass: inetOrgPerson 
objectClass: organizationalPerson 
objectClass: person 
objectClass: top 
sn: pop 
cn: loper 

version: 1 
dn: uid=tuser4,ou=people,o=example.com,o=isp 
userPassword: 
uid: tuser4 
objectClass: inetOrgPerson 
objectClass: organizationalPerson 
objectClass: person 
objectClass: top 
sn: User4 
cn: Test 
+0

Является ли это строго «версия: 1» строк или строк «version: n» или повторных строк в целом? –

+0

Это строго версия: 1 строка, но я хочу сохранить первую версию: 1 строка и удалить остальные – kuti

ответ

5

С GNU sed

sed -ni '0,/version: 1/{p; d}; /version: 1/!p' ldap.txt 

EDIT: Это было изначально неправильно. Когда первая строка не была версией, она печатала дубликаты.

Версия GNU проще. Он печатает (p) с начала до первой строки, соответствующей регулярному выражению версии, включительно. Кроме того, для каждой строки в этом диапазоне после печати мы удаляем пространство шаблонов и запускаем новый цикл (d). В основном это означает переход к началу сценария и к следующей строке (это позволяет избежать двойной печати). В отличие от (стандартного) 1,/regex/, если первая строка соответствует, она не будет продолжать другая соответствующая строка.

Если мы не имеем d «под ред (так мы после первого version: 1), мы тогда просто печатать каждую строку, которая не соответствует регулярному выражению (!).

со стандартным СЕПГОМ):

sed -ni 'p; /version: 1/ b nov; d; :nov /version: 1/!p; n; b nov' ldap.txt 

Это начинает просто печатать каждую строку (p). После этой печати, если мы сопоставим регулярное выражение, мы переходим к метке nov (без версии); имя лейбла зависит от нас. Если мы не ведем ветвь, мы (d) удалим пространство шаблона и начнем новый цикл (новая строка, начало скрипта). В nov мы печатаем строку, если она не соответствует (то же, что и GNU). Затем мы переходим к новой строке и возвращаемся к нову. Этот цикл продолжается до конца.


I (Джонатан Леффлер) может подтвердить наблюдения @ kuti по стандарту Solaris 10 «sed»; что работает это:

/bin/sed -n 'p 
/version: 1/ b nov 
d 
:nov 
/version: 1/!p 
n 
b nov' ldap.txt 

В «полу-колонов вместо Newlines» трюк, кажется, не универсально работать с Solaris «СЭД». В частности, по крайней мере, не может быть полуколонии после любого использования метки.

Это похоже на работу:

/bin/sed -n 'p; /version: 1/ b nov 
d; :nov 
/version: 1/!p; n; b nov' ldap.txt 

(я не могу думать о том, чтобы представить исправления в комментарии - многострочное форматирование имеет решающее значение здесь.)

+0

Я пробовал первое предложение без опции -i, оно работает, но удаляет все вхождения, что не то, что я пытаюсь выполнить. Я хочу сохранить первое вхождение версии: 1, но удалить остальные .... – kuti

+0

@kuti, вы уверены, что используете GNU sed? Версия Solaris по умолчанию - нет. Вы попробовали второе решение? –

+0

Вот что я получаю: root @ solix # sed -n 'p;/версия: 1/b nov; д; : nov/version: 1 /! p; п; b nov 'zdir1-user-entry-full.txt Слишком длинная надпись: p;/версия: 1/b nov; д; : nov/version: 1 /! p; п; b nov – kuti

2

Простого ответа использует AWK :

awk '{ if ($0 ~ /^version: 1$/) { if (count++ == 0) print; } 
     else print; 
    }' 

Это предполагает, что вы на самом деле означает, что вы хотите, только первый «вариант: 1» линию и не против держать несколько «вариант: 2» ли nes и т. д.

+0

Нет, это не то, что я имел в виду. Мне нужно первое появление версии: 1 и удалить оставшуюся часть версии 1 из списка. – kuti

+0

@kuti: Я озадачен - вы говорите: «Это не то, что я имел в виду», но затем продолжайте запрашивать то, что (исправленная ошибкой версия) моего ответа дает вам. –

+0

hmm. Он удалил все вхождения в мое время, когда я попробовал ваше решение awk. Возможно, я не очень хорошо объяснил проблему. Короче говоря, у меня есть список пользователей, которые мне нужны, чтобы получить их данные с сервера ldap. Я делаю это в цикле for: для i в 'cat $ LDAP1-user-list.txt' do ldapsearch -h $ LDAP1 -D" cn = диспетчер каталогов "-w $ PWD -bo = $ DOMAIN, o = $ MYO uid = $ i >> $ LDAP1-user-entry-full.txt сделано Выше за цикл неизбежно получает всю необходимую информацию, но с дополнительной версией: 1 после каждого пользователя. Мне нужно сохранить первую версию: 1 и удалить остальные, так как это стандартный файл ldiff. – kuti

0

вот еще AWK версия

awk '/version: 1/{c++}c>1{gsub("version: 1","")}1' file 
0

Использование человек 1-е изд можно выделить строку, содержащую первый матч и увеличиваем его на 1, чтобы получить:

# 'm+1,$ 
# ... which creates a line address space of: 
# /first line matched + 1/,/last line/ 

# http://wiki.bash-hackers.org/doku.php?id=howto:edit-ed 
[[ $(grep -c -m 1 '^version: 1' file) -eq 1 ]] && \ 
cat <<-'EOF' | sed -e 's/^ *//' -e 's/ *$//' | ed -s file 
    H 
    /^version: 1/km 
    'm+1,$g/^version: 1/d 
    wq 
EOF 
Смежные вопросы