Соответствует только первому вхождению в строке с регулярным выражением


42

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

Задача проста. У меня есть файл CSV с записями, которые читаются так:

12345,67890,12345,67890
12345,67890,12345,67890
12345,67890,12345,67890
12345,67890,12345,67890
12345,67890,12345,67890

Я хотел бы заменить первую запятую пробелом и оставить остальные запятые нетронутыми для каждой строки. Есть ли регулярное выражение, которое будет соответствовать только первой запятой?

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


какой инструмент вы используете? (sed, perl, awk, что-то еще?)
Мат

Textpad (Windows)
cows_eat_hay

Ответы:


53

Соответствующий шаблон может быть:

^([^,]+),

Это означает

^        starts with
[^,]     anything but a comma
+        repeated one or more times (use * (means zero or more) if the first field can be empty)
([^,]+)  remember that part
,        followed by a comma

Например, в Perl все совпадения и замены будут выглядеть так:

s/^([^,]+),/\1 /

Запасная часть просто берет все, что соответствует, и заменяет его первым блоком, который вы запомнили, и добавляет пробел. Кома "отброшена", потому что она не входит в первую группу захвата.


Потрясающе! Спасибо, Мат, это сработало отлично. Это на самом деле не работало в Textpad (я думаю, что их регулярное выражение ограничено), поэтому я в итоге скачал PowerGrep и использовал поиск и замену с предоставленным вами выражением, и это прекрасно работало. Спасибо также за хорошее объяснение, оно помогает понять, что происходит.
cows_eat_hay

7
s/,/ /

Это, по умолчанию (то есть без gопции), заменяет только первое совпадение.


1
Это на самом деле текстовый поиск и замена синтаксиса?
Даниэль Бек

1
Это синтаксис sed, perlи некоторые другие инструменты.
Пабук

3

Это должно соответствовать только первое число и запятая: ^(\d{5}),. Если вы хотите поглотить все остальное в строке, измените регулярное выражение на это:^(\d{5}),(.*)$


Это также сделало свое дело. На самом деле я решил использовать решение Мэта, но я тоже проверил ваше, и оно работает. Спасибо за помощь!
cows_eat_hay

Почему \d{5}и нет [^,]*? Это будет @ по крайней мере более общим.
JustinCB

2

Более элегантное решение - использовать ленивое сопоставление:

s/^(.+?),/\1 /

это сгруппирует символы, перемещаясь от начала строки ( ^) к концу на один символ ( .+?) на каждом шаге, пока не найдет первый знак запятой. Вся эта группа вместе с первым появлением запятой будет заменена \1символом group ( ) и пробелом.


Обратите внимание, что это не будет соответствовать строке, которая не содержит запятой (одно значение в строке). Соответствие любому * может быть лучше, чем один, +так чтоs/^(.*?),/\1 /
Джефф Пукетт

Вы также можете сделать s/^([^,]*),/\1 /что-то, что соответствует началу, что угодно, не запятая, а запятая. Кроме того, разве вы не знаете, что это s//ничего не меняет, не соответствует?
JustinCB

1

TextPad всегда имел возможность использовать нотацию posix, но вы должны изменить настройки в другом диалоговом окне. Чтобы использовать стандартные настройки TextPad для регулярных выражений, вам необходимо «экранировать» открывающие и закрывающие скобки:

Замените пробел после 5-значного почтового индекса в начале каждой строки

^\([0-9]+\)[ ]

С вкладкой

\1\t

Как и выше, ^ означает начало строки

\ (это «экранированная скобка», и она обозначает начало первого поискового выражения, то есть пять цифр

[0-9] + означает одну или несколько цифр (не только 5-значные почтовые индексы)

\) - это еще одна "скобка с пробелом" для обозначения конца первого поискового выражения

[] это просто пробел (вы можете не указывать в скобках, но тогда никто не сможет увидеть его на этой веб-странице :-)

В выражении замены

\ 1 - первое поисковое выражение, часть между круглыми скобками (одна или несколько цифр)

\ t является символом табуляции

Таким образом, команда поиска и замены ищет одну или несколько цифр, за которыми следует пробел. Затем он заменяет все это той же группой цифр, за которой следует вкладка.

Я не думаю, что есть какой-то способ просто найти «пробел после 5 цифр», так что вы можете просто заменить пробел, не касаясь цифр. Вы должны найти 5 цифр (первая строка), а затем пробел (вторая строка). Затем, хотя это кажется избыточным или громоздким, ЗАМЕНИТЕ оригинальную строку из 5 цифр с САМОМ, после чего следует табуляция (вторая строка).

Каждый, кто знает это, забывает, что новички понятия не имеют об этом. Вот почему я говорю это для тебя, мой друг.

Ed Poor Math Tutor и бывший программист в Нью-Йорке


0

Чтобы соответствовать только первому вхождению любого выражения регулярного выражения, удалите все флаги. Каждое выражение регулярного выражения поставляется со следующими возможными флагами и обычно по умолчанию использует глобальный флаг, который будет соответствовать более чем одному вхождению:

  • / g = С этим флагом поиск ищет все совпадения, без него - возвращается только первое совпадение
  • / I = без учета регистра
  • / m = многострочный режим
  • / s = все. чтобы соответствовать символу новой строки \ n
  • / u = Юникод
  • / y = режим закрепления (поиск в определенном месте)
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.