2016-12-31 1 views
1

Мне нужна помощь для синтаксического анализа строки и извлечения слова, разделенного запятой, и назначения значения изнутри [] скобок. Строка ввода, как это:Разбор строки и извлечение слова, разделенного запятой, и назначение значения изнутри [] скобки

KEEP_DFB,?(y/n),[y]; 
DFB_VERSION,?(1.4.2/1.7.6),[1.4.2]: 

и ожидаемый выход

KEEP_DFB=y 
DFB_VERSION=1.4.2 

Ближайший я мог бы достичь с помощью СЭД это:

echo 'KEEP_DFB,?(y/n),[y]:' | sed 's/\([^,]*,\).*,\([^,]*\):.*/\1=\2/' 

, но это не дает результата, как ожидается.

Я также попробовал «разрезать», но тот же результат, что и выше. Использование IFS не допускается для изменения разделителя. Помогите, пожалуйста.

+0

Действительно ли шаблон '(y/n), [y]' всегда выполняется? Я имею в виду даже в '(1.4.2/1.7.6), [1.4.2]' значение внутри '[]' такое же, как значение перед '/' inside'() ' – Sundeep

+1

@Sundeep: поскольку вопрос задает вопрос фиксируя значение между квадратными скобками, было бы неразумно полагаться на совпадение в данных выборки, что та же самая часть материала между круглыми скобками соответствует материалу между квадратными скобками. –

+0

@ JonathanLeffler Да, я так думаю, я не полностью прочитал вопрос, подготовил ответ, а затем заметил мое предположение перед публикацией ... поэтому я попросил разъяснения, поскольку решение было бы проще .. – Sundeep

ответ

2

Вы были довольно близки:

$ printf "%s\n" 'DFB_VERSION,?(1.4.2/1.7.6),[1.4.2]:' 'KEEP_DFB,?(y/n),[y]:' | 
> sed 's/\([^,]*\),.*,\[\([^],]*\)][;:].*/\1=\2/' 
DFB_VERSION=1.4.2 
KEEP_DFB=y 
$ 

Первая запятая перемещается за пределы захвата. Второй захват предшествует \[ (буква [ в данных), за которым следует ] (не требуется обратный слэш, потому что ] является только особенным, когда он является частью класса символов, хотя я был бы очень соблазнен добавьте один, и он отлично работает с обратной косой чертой или без нее).

Sundeep отметил, что существует точка с запятой вместо двоеточия в одной из линий данных, но пример данных в echo имеет двоеточие, а не точкой с запятой (поэтому я не заметил эту проблему на первом проходе , Я скопировал команду прототипа). Это тривиально обрабатывается, используя [;:] как класс символов вместо прямого :.

Отрицаемый класс символов исключает ] и запятые - хотя неясно, почему запятые должны быть исключены. Это означает, что вы не признали бы это действительным:

VERSION_LIST,?(1.2/1.3/1.4/1.7),[1.4,1.7]: 
+0

Большое вам спасибо @Jonathan .. это отлично работает и соответствует сценарию требований .. это именно то, чего я отсутствовал .. Большое вам спасибо за объяснение. –

+0

Извините, я пропустил, чтобы отметить последний пункт ... Да, вы догадались, что это правильно, это будет считаться недействительным. –

0

Вы должны попробовать этот код. Он должен работать нормально.

awk -F"," '{print $1,$3}' OFS="=" file_name | sed -e 's/\[\(.*\)\]./\1/' 

Это будет выводить строки, содержащиеся в файле, используя AWK и заменить разделитель на =, а затем заменить часть, начиная от [ и заканчивая ] или любого другого характера по значениям внутри [].

Вы также можете попробовать это короче один:

sed -e 's/,.*\[\(.*\)\]./=\1/' file 

Выход для обоих:

KEEP_DFB=y 
DFB_VERSION=1.4.2 
+0

или используйте ',' и '[' и ']' в качестве разделителя: 'awk -F '[, [\]]' '{print $ 1" = "$ 4}' file' – Cyrus

+0

@VinnyAdjibi: Нет необходимости используйте 1 awk, а затем 1 sed, вы можете обернуть его в течение одного единственного awk (кроме того, что предложил Кир). awk -F "," '{gsub (/ \ [| \] |; |: /, X, $ 3); print $ 1, $ 3}' OFS = "=" Input_file – RavinderSingh13

+0

@RavinderSingh: Спасибо за совет. Я не знал о gsub. Конечно, это более короткий и быстрый способ решить эту проблему. – VinnyAdjibi

3

Я предлагаю:

sed 's/,.*\[/=/;s/].//' file 

Выход:

 
KEEP_DFB=y 
DFB_VERSION=1.4.2 
+0

Благодарю вас, @Cyrus, хотя он работает для данного примера, но также, я должен время от времени выделять слова и хранить его, как в \ 1 \ 2 \ 3 .. Джонатан только что ответил мне до сути .. и Это помогает мне понять мою недостающую точку в приведенном выше примере. –

0
awk -F'[][,]' '{print $1"="$4}' file 

KEEP_DFB=y 
DFB_VERSION=1.4.2 
0

Вы не сказали, что оболочка вы собираетесь использовать, но с большинством оболочек, следующий подход будет работать:

# Drop the last two characters 
x=${original:0:-2} 
# Store the name part 
name=${x%%,*} 
# Store the value part 
value=${x##*\[} 

Например, если original содержит DFB_VERSION,?(1.4.2/1.7.6),[1.4.2]:, name будет содержать DFB_VERSION и value будет содержать 1.4.2.

BTW, почему вы не хотите изменять IFS? Конечно, вы не хотите постоянно менять его, но его изменение только для одного утверждения не влияет на остальную часть программы.

+0

Кажется, что сценарий должен запускаться на другом сервере сборки, у пользователей может не быть разрешения «root/superuser», или IFS может быть отключен. Таким образом, существующее решение с IFS работало для «корневых» пользователей, пока оно застревает у других. –

+0

Вам не нужно иметь разрешение суперпользователя на изменение IFS, и я не вижу способа, чтобы модификация IFS могла быть «отключена». – user1934428

1
метод оболочки

POSIX, данный входной файл 'Foo':

while IFS=',[]' read a b c d e ; do echo "$a${a:+=}$d" ; done < foo 

Выход:

KEEP_DFB=y 
DFB_VERSION=1.4.2 
+1

В чем преимущество '$ {a: + =}' over '=' здесь? Не печатать ли что-нибудь вообще для пустых строк? Если это так, небольшое объяснение поможет. –

+1

@BenjaminW., Это правильно, без '$ {a: + =}' выход имел бы бесполезные '=' знаки всякий раз, когда строка была пустой. Это немного быстрее, чем выполнение: '[" $ a "] && echo" $ a $ = $ d "' – agc

0

@Suresh K: Не могли бы вы, пожалуйста, попробуйте следующее и дайте мне знать, если это поможет вам ,

awk -F, '{match($0,/\[.*\]/);print $1"="substr($0,RSTART+1,RLENGTH-2)}' Input_file 

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

Смежные вопросы