sed извлекает из файла несколько возможных (?) значений - PullRequest
3 голосов
/ 16 сентября 2010

У меня есть файл, который состоит из нескольких строк, например:

"<sender from="+919892000000" msisdn="+919892000000" ipAddress="" destinationServerIp="" pcfIp="" imsi="892000000" sccpAddress="+919895000005" country="IN" network="India::Airtel (Kerala)"
"<sender from="+919892000000" msisdn="+919892000000" ipAddress="" destinationServerIp="" pcfIp="" sccpAddress="+919895000005" country="IN" network="India::Airtel (Kerala)"

В первой imsi существует, а во второй imsi не существует Для каждой строки, которая начинается со слова sender (тамдругие строки в файле) Я хочу извлечь как значение msisdn, так и значение imsi.Если значение imsi отсутствует, я бы напечатал строку imsi: Unknown.

Я пробовал следующее, но оно не работает:

/sender / { /msisdn/ {s/.*msisdn=\"([^\"]*)?\".*/msisdn: \1/}; p; /imsi/ {s/.*imsi=\"([^\"]*)?\".*/imsi: \1/}; /imsi/! {s/.*/imsi: Unknown/}; p};

Чего мне не хватает?

A

Ответы [ 4 ]

1 голос
/ 16 сентября 2010

Ваш матч для "msisdn" удаляет "imsi", поэтому всегда берется отрицательное совпадение.Просто скопируйте вашу строку в область удержания, выполните обработку "msisdn", поменяйте область удержания обратно в пространство шаблона, затем выполните обработку "imsi":

/sender / {h; /msisdn/ {s/.*msisdn=\"([^\"]*)?\".*/msisdn: \1/}; p;x; /imsi/ {s/.*imsi=\"([^\"]*)?\".*/imsi: \1/}; /imsi/! {s/.*/imsi: Unknown/};p}
1 голос
/ 16 сентября 2010

Это можно сделать с помощью следующего сценария sed:

s/^.*sender .*msisdn="\([^"]*\)" .* imsi="\([^"]*\)".*$/msisdn: \1, imsi: \2/
t
s/^.*sender .*msisdn="\([^"]*\)".*$/msisdn: \1, imsi: Unknown/
t
d
  • Первая команда s напечатает все строки отправителя, содержащие imsi поле.
  • Первая команда t будет продолжена со следующей строкой, если предыдущий Команда выполнена успешно.
  • Вторая команда t напечатает все линии отправителя без поля imsi.
  • Вторая команда t будет продолжена со следующей строкой, если предыдущий Команда выполнена успешно.
  • Команда d удалит все остальные линии.

Чтобы запустить этот скрипт, просто скопируйте его в файл и запустите, используя скрипт sed -f.

1 голос
/ 16 сентября 2010

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

cat xmlEventLog_2010-03-23T* | 
sed -nr "/<event eventTimestamp/,/<\/event>/  {
/event /{/uniqueId/ {s/.*uniqueId=\"([^\"]+)\".*/\nuniqueId: \1/g}; /uniqueId/!  {s/.*/\nuniqueId: Unknown/}; p};
/payloadType / {/type/ {s/.*type=\"([^\"]+)\".*/payload: \1/g}; /type/! {s/.*protocol=\"([^\"]+)\".*/payload: \1/g}; p}; 

***/sender / { /msisdn/ {s/.*msisdn=\"([^\"]*)?\".*/msisdn: \1/}; p; /imsi/ {s/.*imsi=\"([^\"]*)?\".*/imsi: \1/}; p; /imsi/! {s/.*/imsi: Unknown/}; p};

/result /{s/.*value=\"([^\"]+)\".*/result: \1/g; p}; /filter code/{s/.*type=\"([^\"]+)\".*/type: \1/g; p}}" 

| awk 'BEGIN{FS="\n"; RS=""; OFS=";"; ORS="\n"} $4~/payload: SMS-MT-FSM-INFO|SMS-MT-FSM|SMS-MT-FSM-DEL-REP|SMS-MT-FSM-DEL-REP-INFO|SMS-MT-FSM-DEL-REP/ && $2~/result: Blocked|Modified/ && $3~/msisdn: +919844000011/ {$1=$1 ""; print}'

Это анализирует файлы, заполненные событиями, например:

       <event eventTimestamp="2010-03-23T00:00:00.074" originalReceivedMessageSize="28" uniqueId="1280361600.74815_PFS_1_2130328364" deliveryReport="true">
            <result value="Allowed"/>
            <source name="MFE" host="PFS_1"/>
            <sender from="+919892000000" msisdn="+919892000000" ipAddress="" destinationServerIp="" pcfIp="" imsi="892000000" sccpAddress="+919895000005" country="IN" network="India::Airtel (Kerala)">
                    <profile code=""/>
                    <mvno code=""/>
            </sender>
            <recipients>
                    <recipient code="+919844000039" imsi="892000000" SccpAddress="+919895000005" country="IN" network="India::Airtel (Kerala)">
                    </recipient>
            </recipients>
            <payload>
                    <payloadType protocol="SMS" type="SMS-MT-FSM-DEL-REP"/>
                    <message signature="70004b7c9267f348321cde977c96a7a3">
                            <MailFrom value=""/>
                            <rcptToList>
                            </rcptToList>
                            <pduList>
                                    <pdu type="SMS_SS_REQUEST_IND" time="2010-07-29T00:00:00.074" source="SMSPROBE" dest="PCF"/>
                                    <pdu type="SMS_SS_REQ_HANDLING_STOP" time="2010-07-29T00:00:00.074" source="PCF" dest=""/>
                            </pduList>
                            <numberOfImages>0</numberOfImages>
                            <attachments numberOf="1">
                                    <attachment index="0" size="28" contentType="text/plain"/>
                            </attachments>
                            <emailSmtpDeliveryStatus value="" time="" reason=""/>
                            <pepId value="989350000109.989350000209.0.0"/>
                    </message>
            </payload>
            <filters>
            </filters>
    </event>

Может быть до 10000 событий, например, над каждым файлом, и будут сотни файлов. Выходные структуры для awk должны быть типа:

uniqueId: 1280361600.208152_PFS_1_1509661383
result: Allowed
msisdn: +919892000000
imsi: 892000000
payload: SMS-MT-FSM-DEL-REP
filter:

По этой причине мне нужно извлечь 2 значения из строки отправителя и другие значения из других строк. Вышеупомянутый фильтр извлекает все правильно, за исключением части, когда найдена линия отправителя (помечена *** в фильтре) Поэтому я просто хочу извлечь 2 элемента из строки отправителя для структуры. Несколько попыток потерпели неудачу.

0 голосов
/ 16 сентября 2010

Я использовал Perl для решения вашей проблемы.

cat file | perl -n -e 'if (/sender.*msisdn="([^"]*)"(.*imsi="([^"]*)")?/) { print $1, " ", $3 || "unknown", "\n"; }'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...