Первый проход - работает, но неуклюже
Вот решение, которое работает с GNU и BSD sed
:
sed -E \
-e '/\[[[:alnum:] ,]+\]/ {
s/\[([[:alnum:] ,]+)\]/^B\1^E/
:a
s/(^B[[:alnum:],]*) +/\1/
t a
s/^B/[/
s/^E/]/
}' \
data
Появления ^B
и ^E
являются управляющими символами ( Control-B и Control-E в оригинале), которые не будут появляться в реальном тексте.(При первом копировании я получил ^B
, показывающий как и ^E
, показывающий как.)
Объяснение:
/\[[[:alnum:] ,]+\]/ {
- сопоставление строк, содержащих квадратные скобки, с буквенно-цифровыми символами плюс пробели запятую между ними, и выполните последовательность действий от {
до соответствующего }
. s/\[([[:alnum:] ,]+)\]/^B\1^E/
- замените квадратные скобки управляющими символами. :a
-установите метку s/(^B[[:alnum:],]*) +/\1/
- замените ^B
плюс последовательность буквенно-цифровых или запятых (которые захвачены) и строку из одного или нескольких пробелов только с захватом. t a
- если команда s///
внесла изменение, вернитесь к метке a
. s/^B/[/
- замените ^B
на квадратную скобку. s/^E/]/
- замените ^E
закрывающей квадратной скобкой. }
- выполнено
Ответвление необходимо, потому что обычно оператор s///
не сканирует материал, который онтолько что заменил, в то время как крайне важно, чтобы это продолжало повторное сканирование.
С учетом немного более обширного входного файла:
\[[a-zA-Z0-9 ,]+\] (caseless alphanum comma and space, between square brackets)
For example:
[ "This is a test": [a, b c] ]
[ "This is a test": [a, b, c] ]
[ "This is test 3": [ XXX, YYY, XXX ] ]
Should become:
[ "This is a test": [a,bc] ]
[ "This is a test": [a,b,c] ]
[ "This is test 3": [XXX,YYY,XXX] ]
скрипт генерирует:
\[[a-zA-Z0-9 ,]+\] (caseless alphanum comma and space, between square brackets)
For example:
[ "This is a test": [a,bc] ]
[ "This is a test": [a,b,c] ]
[ "This is test 3": [XXX,YYY,XXX] ]
Should become:
[ "This is a test": [a,bc] ]
[ "This is a test": [a,b,c] ]
[ "This is test 3": [XXX,YYY,XXX] ]
Второй проход - платит за просмотр и уточнение
Глядя на него^E
не является обязательным, и, возможно, не ^B
также.Версия выше имеет дело только с первым таким набором квадратных скобок в строке.Вам нужно более чувствительные регулярные выражения детекторов (те, которые требуют хотя бы одного пробела между маркерами) для обработки нескольких таких шаблонов в одной строке.
Например:
sed -E \
-e ':a
/\[[[:alnum:],]* [[:alnum:] ,]*\]/ s/(\[[[:alnum:],]*) +/\1/
t a' \
data
Объяснение:
:a
- установить метку /\[[[:alnum:],]* [[:alnum:] ,]*\]/
- если строка содержит открытую квадратную скобку, ноль или более буквенно-цифровых или запятых символов, один или несколько пробелов,и ноль или более буквенно-цифровых или или запятых или пробелов, за которыми следует закрывающая квадратная скобка, затем… s/(\[[[:alnum:],]*) +/\1/
- заменить открытый квадрат и последовательность из нуля или более буквенно-цифровых или запятых символов и одного илибольше пропусков только по непробелам и… t a
- перейти к метке a
, если была сделана замена
Дано:
[ "This is a test": [a, b c] ]
[ "This is test 2": [a, b, c] ]
[ "This is test 3": [ XXX , YYY , XXX ] ]
[ "This is test 4": [ XXX , YYY , XXX ] [ 1 , 2 , 3 ] ]
[ "This is test 5": [ XXX , YYY , XXX ] [ 1 , 2 , 3 ] [ abc ] [ ] ]
это дает:
["This is a test": [a,bc] ]
["This is test 2": [a,b,c] ]
["This is test 3": [XXX,YYY,XXX] ]
["This is test 4": [XXX,YYY,XXX] [1,2,3] ]
["This is test 5": [XXX,YYY,XXX] [1,2,3] [abc] [] ]
Это в основном эквивалентно ответу по Beta ;это можно еще больше упростить, исключив совпадение перед командой замены и изменив (слегка усложняя) замену, чтобы она соответствовала работе Beta.