Awk сопоставление с образцом и обработка пропущенных полей - PullRequest
1 голос
/ 26 сентября 2019

У меня есть некоторые данные из вывода ldapsearch, который выглядит следующим образом:

> echo "$OUTPUT"
sn: name1
uid: uname1
mail: user1@mail.com
roomNumber: e2

sn: name2
uid: uname2
mail: user2@mail.com
roomNumber: e2

sn: name3
uid: uname3
roomNumber: e2

sn: name4
uid: uname4
mail: user4@mail.com
roomNumber: e2

Я использую awk, чтобы обработать каждого пользователя в одну строку, чтобы он заканчивался следующим образом:

name1|uname1|user1@mail.com|e2
name2|uname2|user2@mail.com|e2
name3|uname3||e2
name4|uname4|user4@mail.com|e2

Проблема в том, что мой код ниже не может обработать отсутствующий атрибут mail, поэтому он использует переменную предыдущего пользователя и выглядит следующим образом:

name1|uname1|user1@mail.com|e2
name2|uname2|user2@mail.com|e2
name3|uname3|user2@mail.com|e2
name4|uname4|user4@mail.com|e2

Используемая команда awk:

echo "$OUTPUT" | awk -v OFS='|' '{split($0,a,": ")} \
    /^sn:/{sn=a[2]} \
    /^uid:/{uid=a[2]} \
    /^mail:/{mail=a[2]} \
    /^roomNumber:/{room=a[2]; print sn, uid, mail, room}'

Есть ли способ обработать отсутствующий атрибут, такой как mail, в приведенном выше примере, пожалуйста?

Спасибо.

Ответы [ 3 ]

2 голосов
/ 26 сентября 2019

Как вы заметили, ваш вклад очень хорошо структурирован в записях.Каждая запись отделяется набором пустых строк.Вы можете использовать это с awk.

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

sn: name2
uid: uname2
mail: user2@mail.com
roomNumber: e2

Мыскажет awk извлечь соответствующую информацию и сохранить ее в массиве data.Затем мы будем использовать этот массив для перестройки данных так, как вы хотите.Если ключ не существует в записи, он возвратит пустое значение при запросе:

awk 'BEGIN{RS=""; FS="\n"; OFS="|"}
     { delete data; }
     { for(i=1;i<=NF;++i) {
          match($i,/: +/);
          key=substr($i,1,RSTART-1); value=substr($i,RSTART+RLENGTH);
          data[key]=value }
     }
     { print data["sn"], data["uid"], data["mail"], data["roomNumber"] }' file

Этот метод очень универсален и чрезвычайно гибок, если вы хотите что-то изменить позже.

На представленном примере это выводит:

name1|uname1|user1@mail.com|e2
name2|uname2|user2@mail.com|e2
name3|uname3||e2
name4|uname4|user4@mail.com|e2
1 голос
/ 26 сентября 2019

Предполагая, что ваши входные строки для каждой записи всегда упорядочены, как показано, и это только поле электронной почты, которое может отсутствовать:

$ awk -v RS= -F': |\n' -v OFS='|' '{print $2, $4, (NF>6 ? $6 : ""), $NF}' file
name1|uname1|user1@mail.com|e2
name2|uname2|user2@mail.com|e2
name3|uname3||e2
name4|uname4|user4@mail.com|e2
0 голосов
/ 26 сентября 2019

Просто установите переменные в пустую строку после печати:

$ awk -v OFS='|' '{split($0,a,": ")} 
    /^sn:/{sn=a[2]} 
    /^uid:/{uid=a[2]} 
    /^mail:/{mail=a[2]} 
    /^roomNumber:/{room=a[2]; print sn, uid, mail, room; sn=uid=mail=room=""}' file

name1|uname1|user1@mail.com|e2
name2|uname2|user2@mail.com|e2
name3|uname3||e2
name4|uname4|user4@mail.com|e2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...