Получение точного паттерна Совпадение с grep и sed - PullRequest
0 голосов
/ 09 ноября 2019

Я решаю кучу текстовых строк, используя grep и sed, в которых я хочу, чтобы stdout печатал данные после package: иоканчивается на имя папки без окончания /.

Например:

data/dataapp/com.android.chrome-DeX_54==
System/app/Keychain
vendor/app/NlpService

Это пример ...

package:data/app/com.android.chrome-DeX_54==/base.apk=com.android.chrome
package:data/dataapp/ExactCalculator/ExactCalculator.apk=com.android.calculator2
package:data/hw_init/cust/app/Email/Email.apk=com.android.email
package:system/app/KeyChain/KeyChain.apk=com.android.keychain
package:system/delapp/WallpaperBackup/WallpaperBackup.apk=com.android.wallpaperbackup
package:system/framework/framework-res.apk=android
package:system/priv-app/CIT/CIT.apk=com.ontim.cit
package:vendor/app/NlpService/NlpService.apk=com.mediatek.nlpservice

Я не получаю точный вывод, который мне нужен, поэтому любая помощь будет принята.

PS: Я учусь grep и sed просто для удовольствия.

Ответы [ 2 ]

1 голос
/ 09 ноября 2019

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

sed -n 's#^package:\(.*\)/.*#\1#p' file

Поскольку это может быть операция фильтрации, используйте параметр -n для явной печати результатов. Регулярное выражение начинается с ^ в команде замещения, которая привязывает package: к началу строки и использует .* для жадного использования оставшейся части строки. Однако следующий символ, который он пытается найти, это /, и поэтому механизм регулярных выражений возвращает его назад, а затем следующий .* снова поглощает оставшуюся часть строки. Процитированные в кавычки \(...\) фиксируют эту часть регулярного выражения, и она представлена ​​в RHS команды замены вместо \1, известной как обратная ссылка. Флаг p в конце команды замены явно печатает исправленную строку в ее текущем состоянии.

NB. Что с командой замены, программист может выбрать ее разделитель. В документации команда обычно пишется s/LHS/RHS/flags, где разделитель равен /, но может быть любым символом, как в приведенном выше решении # было выбрано, чтобы уменьшить необходимость в цитировании символа /, LHS = regexp наслева, RHS = замена и флаги = дополнительные операции, такие как g, означающие глобальное замещение по всей строке / файле, и p, означающие печать строки в ее текущем состоянии после успешной замены (другие см. в документации по sed.

1 голос
/ 09 ноября 2019

Не могли бы вы попробовать:

grep -Po '(?<=package:).+(?=/[^/]*$)' input.txt

Результаты:

data/app/com.android.chrome-DeX_54==
data/dataapp/ExactCalculator
data/hw_init/cust/app/Email
system/app/KeyChain
system/delapp/WallpaperBackup
system/framework
system/priv-app/CIT
vendor/app/NlpService
  • Опция -P включает регулярное выражение, совместимое с Perl.
  • The *Параметр 1011 * указывает grep печатать только совпадающие подстроки.
  • Шаблон (?<=package:) представляет собой positive lookbehind assertion, и подобранная подстрока не включается в выходные данные grep -o.
  • Шаблон (?=/[^/]*$) также является positive lookahead assertion.

Альтернативой sed будет:

sed 's#\(^package:\)\(.\+\)\(/[^/]*$\)#\2#' input.txt

или

sed -E 's#(^package:)(.+)(/[^/]*$)#\2#' input.txt

Последний будет более разборчивым.

Вы увидите, что positive lookarounds можно заменить обратной ссылкой sed, просто отбросив ненужные группы.

Надеюсь, этопомогает.

...