Как заменить значение запроса после определенного шаблона в текстовом файле? - PullRequest
0 голосов
/ 26 января 2019

Solaris, ВЕРСИЯ: 11.10.0, REV = 2005.01.21.15.53
У меня есть файл test.txt, который содержит значения, как показано ниже:

 <Info>
     <AccountNumber>23456789</AccountNumber>
     <BranchNumber>004</BranchNumber>
     <TransitNumber>01646</TransitNumber>
     <NameAndCity>XYZ Bank</NameAndCity>
     <OwnerFullName>ABC XYZ</OwnerFullName>
  </Info>

Вся информация в строкеи у нас есть несколько строк, как и выше, также доступны другие теги.

Содержит и другие значения тегов.Также, если значения тега содержат комбинацию «333», я не хочу их заменять.

Я хочу использовать команду sed для замены значения тега на 33333, и после замены я хочу сохранить обновленноеинформация в тот же файл.
Вывод должен быть:

 <Info>
     <AccountNumber>33333333</AccountNumber>
     <BranchNumber>33333</BranchNumber>
     <TransitNumber>3333333</TransitNumber>
     <NameAndCity>333 33333</NameAndCity>
     <OwnerFullName>3333 33333</OwnerFullName>
  </Info>

Я новичок в сценарии оболочки и не могу точно написать шаблон для его соответствия.

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

sed 's/(<AccountNumber>)\+[0-2,4-9]*$/\1 33333333/' test.txt
sed 's/(<BranchNumber>)\+[0-2,4-9]*$/\1 33333/' test.txt

Любая помощь будет оценена.

Ответы [ 3 ]

0 голосов
/ 26 января 2019
$ cat file.txt 
<Info>
    <AccountNumber>23456789</AccountNumber>
    <BranchNumber>004</BranchNumber>
    <TransitNumber>01646</TransitNumber>
    <NameAndCity>XYZ Bank</NameAndCity>
    <OwnerFullName>ABC XYZ</OwnerFullName>
</Info>
<Info>
    <AccountNumber>23456789</AccountNumber>
    <BranchNumber>004</BranchNumber>
    <TransitNumber>01646</TransitNumber>
    <NameAndCity>333 Bank</NameAndCity>
    <OwnerFullName>ABC XYZ</OwnerFullName>
</Info>

$ sed -r '/.*333 /!s#^(\s*<[^>]+>).*(</[^>]+>)$#\133333\2#;s|^(\s*<[^>]+>333 ).*(</[^>]+>)$|\133333\2|' file.txt
<Info>
    <AccountNumber>33333</AccountNumber>
    <BranchNumber>33333</BranchNumber>
    <TransitNumber>33333</TransitNumber>
    <NameAndCity>33333</NameAndCity>
    <OwnerFullName>33333</OwnerFullName>
</Info>
<Info>
    <AccountNumber>33333</AccountNumber>
    <BranchNumber>33333</BranchNumber>
    <TransitNumber>33333</TransitNumber>
    <NameAndCity>333 33333</NameAndCity>
    <OwnerFullName>33333</OwnerFullName>
</Info>

Первые строки отрицания, в которых есть ">333 " с /.*333 /!. На такие строки будет влиять второе регулярное выражение s#^(\s*<[^>]+>).*(</[^>]+>)$#\133333\2#;. Строки, содержащие ">333 ", будут изменены в соответствии с s|^(\s*<[^>]+>333 ).*(</[^>]+>)$|\133333\2|.

Добавьте параметр -i в sed для применения изменений.

EDIT:

Как прокомментировал @Tiw, лучше использовать perl вместо sed:

$ perl -pe 's#<([^>]+)>(?:(?!333).)*</\1>#<\1>333333333<\1>#;s#<([^>]+)>333 .*#<\1>333 3333</\1>#' -i file.txt
<Info>
    <AccountNumber>333333333<AccountNumber>
    <BranchNumber>333333333<BranchNumber>
    <TransitNumber>333333333<TransitNumber>
    <NameAndCity>333333333<NameAndCity>
    <OwnerFullName>333333333<OwnerFullName>
</Info>
<Info>
    <AccountNumber>333333333<AccountNumber>
    <BranchNumber>333333333<BranchNumber>
    <TransitNumber>333333333<TransitNumber>
    <NameAndCity>333 3333</NameAndCity>
    <OwnerFullName>333333333<OwnerFullName>
</Info>

Примечание: опция -i применяет изменения к файлу.

0 голосов
/ 27 января 2019

Размещение с правильными данными для будущих пользователей:

perl -pe 's#<([^>]+)>(?:(?!333).)*</\1>#<\1>333333333<\1>#;s#<([^>]+)>333 .*#<\1>333 3333</\1>#' -i file.txt

Выше будет заменено все значение тега на 333333333, даже если это не теги AccountNumber, BranchNumber..etc, оно также заменит другие значения тегов. также NameAndCity и OwnerFullName являются буквенно-цифровыми, поэтому нам необходимо добавить Regex с буквенно-цифровым / специальным / пробелом для них. Вот ответ:

perl -i -pe 'unless (/333/) {s#<AccountNumber>[0-9]*</AccountNumber>#<AccountNumber>33333333</AccountNumber>#;
        s#<BranchNumber>[0-9]*</BranchNumber>#<BranchNumber>33333</BranchNumber>#;
        s#<TransitNumber>[0-9]*</TransitNumber>#<TransitNumber>3333333</TransitNumber>#;
        s#<NameAndCity>[A-Za-z\ \-\+]*</NameAndCity>#<NameAndCity>333 33333</NameAndCity>#;
        s#<OwnerFullName>[A-Za-z/\/\ \+]*</OwnerFullName>#<OwnerFullName>3333 33333</OwnerFullName>#;}' test.txt 
0 голосов
/ 26 января 2019

Попробуйте это:

sed -e '/333/!{' -e 's#<AccountNumber>[0-9]*</AccountNumber>#<AccountNumber>333333333</AccountNumber>#;s#<BranchNumber>[0-9]*</BranchNumber>#<BranchNumber>33333</BranchNumber>#;}'

Например:

$ sed -e '/333/!{' -e 's#<AccountNumber>[0-9]*</AccountNumber>#<AccountNumber>333333333</AccountNumber>#;s#<BranchNumber>[0-9]*</BranchNumber>#<BranchNumber>33333</BranchNumber>#;}'  test.txt
 <Info>
     <AccountNumber>333333333</AccountNumber>
     <BranchNumber>33333</BranchNumber>
     <TransitNumber>01646</TransitNumber>
     <NameAndCity>XYZ Bank</NameAndCity>
     <OwnerFullName>ABC XYZ</OwnerFullName>
  </Info>

Очень простой способ, если вы тестируете нормально и хотите изменить файл на месте, добавьте переключатель -i.

У меня нет Solaris для тестирования, поэтому я не уверен.

Попробуйте этот простой perl один, посмотрите, работает ли он:

perl -pe 's#<AccountNumber>[0-9]*</AccountNumber>#<AccountNumber>333333333</AccountNumber>#' test.txt

Если он работает, мы можем добавить другие.

Итак, для вашей логики сначала написано ввопрос, это должно быть так:

perl -pe 'unless (/333/) {s#<AccountNumber>[0-9]*</AccountNumber>#<AccountNumber>333333333</AccountNumber>#;s#<BranchNumber>[0-9]*</BranchNumber>#<BranchNumber>33333</BranchNumber>#;}' test.txt

Вы можете добавить другие замены самостоятельно.# должен заменить обычный / из s, более простой способ избежать экранирования / в тегах закрытия (IE s#from#to#;).
Это довольно просто, так что я думаю, что у вас будетбез затруднений:)
Добавить -i переключатель, чтобы изменить место, как это: perl -i -pe '....

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