Кращий спосіб зробити "echo $ x | sed… ”та“ echo $ x | греп… »


13

Я часто знаходжу це в сценаріях (і, маю визнати, написати це сам):

a=$(echo "$x" | sed "s/foo/bar/")

або

if echo "$x" | grep -q foo
then
    ...
fi

Розгляньте "foo", щоб включити кілька регекс-матеріалів.

Я відчуваю, що має бути - і, швидше за все , - кращий спосіб сформулювати це слово, яке не передбачає двох команд і труби, але вкладає річ у якийсь більш компактний вираз.

Я просто не можу його знайти. Хтось?


Я очікую, що цей вираз використовується часто через поєднання незнання (не знаючи альтернатив) та ремонтопридатності (знаючи альтернативи, але вибираючи це як простіший для розуміння). я можу з першого погляду розповісти, що роблять ваші приклади, але мені потрібна посилання на оболонку, щоб з'ясувати альтернативи відповідей Grawity та Дана Макга.
крякати кіхот

3
До речі, кращий метод заміни команд - це $()замість зворотних посилань.
Денніс Вільямсон

2
Також непогано процитувати розширення, щоб захищений пробіл був захищений: a="$(echo "$x" | sed "s/foo/bar/")"і if echo "$x" | grep foo; ….
Кріс Джонсен

Хороші зауваження щодо $ () проти ``. Я бачу, що мої баш-навички ще не такі великі.
DevSolar

Відповіді:


11

Якщо ви не припустите конкретну оболонку, немає кращого способу зробити це, ніж "ехо на інструмент" (або просто "інструмент", як expr ); це все, на що ви справді можете розраховувати з традиційною оболонкою Bourne та / або оболонкою POSIX . Якщо розглянути інші снаряди, то є ще деякі вбудовані можливості.

ksh має

  • додаткові моделі: ?(pattern-list), *(pattern-list), {n}(pattern-list), {n,m}(pattern-list), @(pattern-list), !(pattern-list);
  • %P Printf специфікатор , щоб перетворити розширене регулярний вираз в зразок (і %Rдля розширеного регулярного виразу до шаблону);
  • expr == patternумова [[ expr ]]випробувань;
  • ${param/pattern/replacement}розширення параметра.

баш має

  • extglobваріант для того, щоб більшість додаткових моделей KSH (немає {n}і {n,m});
  • expr == patternумова (в [[ expr ]]тестах);
  • ${param/pattern/replacement}розширення параметра;
  • (у нових версіях) expr =~ extregexpумова (у [[ expr ]]тестах), яка може відповідати розширеним регулярним виразам
    • за допомогою скобкових виразів у дужках та BASH_REMATCHпараметру можна зробити заміну sed -style.

zsh має

  • власні розширені візерунки з EXTENDED_GLOBопцією;
  • ksh- подібні розширені візерунки з KSH_GLOBопцією;
  • expr == patternумова (в [[ expr ]]тестах);
  • ${pattern/pattern/replacement}розширення параметра;
  • expr =~ extregexpумова (в [[ expr ]]тестах) , які можуть відповідати проти розширених регулярних виразів,
    • він може використовувати PCRE замість простих розширених регулярних виразів, якщо встановлено параметр RE_MATCH_PCRE,
    • за допомогою круглих дужок, MATCHпараметру та matchпараметра (або BASH_REMATCHз BASH_REMATCHнабором опцій) можна зробити заміну sed -style;
  • zsh/pcreмодуль , який пропонує pcre_compile, pcre_studyі pcre_matchкоманду і -pcre-match тест виконується умова (в [[ expr ]]тестах);
  • zsh/regexмодуль , який пропонує -regex-match тестове умова (в [[ expr ]]тестах).

Ого. Настільки повно, як можна було б побажати. Однозначно переможець.
DevSolar

6

Щоб замінити лінію sed, зробіть щось подібне

${a/foo/bar} або ${a//foo/bar}

У першій формі замінюється лише перша інстанція. Друга форма - це глобальний пошук і заміна.

У вашому випадку це було б

Замість:

if echo $x | grep foo
then
    ...
fi

Подумайте про використання:

if [ $x =~ foo ]
then
    ...
fi

Де fooрегулярний вираз.


У яких оболонках це працює?
Пельтьє

1
if [ $x =~ foo ]надає повідомлення про помилку тут. if [[ $x =~ foo ]]однак, чудово працює. Дякую!
DevSolar

1
Все це башизми, вони вимагають баш. Крім того, =~потрібно bash> = 3 iirc.
phaphink

1
Iirc також, foo не є регулярним виразом (як у PCRE) у цих прикладах, але використовує підстановку. Більше цих башівських благ є в баш-сторінці, розділ "Розширення параметрів". Я особливо ціную такі речі, як ${a##foo}і ${a%%bar}.
phaphink

3
Оператор відповідності =~використовує регулярні вирази. Це вірно, наприклад: [[ "abcdddde" =~ ^a.*d+.g* ]](наприклад, це нульовий чи більше g, а не g-wildcard).
Денніс Вільямсон

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.