2016-03-08 6 views
5

У меня есть файл, который содержит много строк (разделитель строк ~). В каждой строке у меня много элементов, разделенных разделителем '*'. Что я хочу сделать, У меня будет строка, которая начинается с строки TRN в моем файле. Он может содержать 4 (включая TRN) или больше точек данных. Что-то вроде,Как заменить часть строки на sed?

TRN*1*S521000035*1020494919~ 
TRN*1*S521000035*1020494919*787989800~ 

Я хочу заменить четвертую точку данных с этих строк на abc123. т.е.

TRN*1*S521000035*abc123~ 
TRN*1*S521000035*abc123*787989800~ 

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

sed -i 's/^TRN\*(.*)\*(.*)\*(.*)$/abc123/g' file.txt 

Но вся строка становится заменена на abc123.

Возможно ли изменить только его 4-й канал с помощью команды sed?

ответ

2

Использование GNU СЭД:

$ sed -r -i 's/^((\w+\*){3})\w*(.*)/\1abc123\3/g' file.txt 

Выход:

TRN*1*S521000035*abc123~ 
TRN*1*S521000035*abc123*787989800~ 
+0

Работал. Большое спасибо! –

+0

В приведенном выше случае я хотел заменить четвертую точку данных, только если первая точка данных TRN. Поэтому я настроил вашу команду как «sed -r -i 's/^ (TRN \ *) ((\ w + \ *) {2}) \ w * (.*)/\ 1 \ 2abc123 \ 4/g '' –

2

sed - твой друг.

Дайте попробовать на этой тестируемой версии:

$ sed "s/^\(TRN[*][^*][^*]*[*][^*][^*]*[*]\)[^*][^*]*\(.*~\)/\1abc123\2/" afile.txt 
TRN*1*S521000035*abc123~ 
TRN*1*S521000035*abc123*787989800~ 

Вы могли бы хотеть прочитать страницы человека, чтобы получить более подробную информацию о регулярных выражений и SED

0

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

$ awk 'BEGIN { FS="*|~" }{ sub($4, "abc123"); print $0}' file.txt 

TRN*1*S521000035*abc123~ 
TRN*1*S521000035*abc123*787989800~ 
+0

Почему вы не используете' $ 4 = "abc123" '? Выполнение субпользователя - это немного странно. –

+0

Потому что когда я сделал это, он удалил «*» между полями и «~» с конца первой строки. Не знаю, почему это было сделано, но проблема была решена. –

+0

Поскольку вы не установили разделитель выходного поля OFS. –

0

В то время как вы можете сделать это с помощью СЭД намного легче достичь желаемого эффекта с AWK. Программа AWK особенно полезен для анализа и преобразования табличных данных структурированы, как в вашем случае:

awk -F'*' -v OFS='*' '{$4 = "abc123"; print}' 

Это читает:

awk   Run the program awk 
-F'*'  Use the * as a field delimiter on input 
-v OFS='*' Use the * as a field delimiter on output 
'{   On each record … 
    $4 = "abc123"; 
      … set the 4th field to "abc123" 
    print 
      … and print the curent record 
    }' 

Это также легко расширить этот пример, чтобы выборочно замените 4-е поле, в зависимости от значения других полей.

+1

Ваша команда 'awk' удаляет' ~ 'в конце строки 1 в примере и это нежелательное поведение. – user3439894

+0

'awk 'BEGIN {ORS = RS =" ~ \ n "; FS = OFS =" * "} $ 4 =" abc123 "'' – 123

+1

@ 123, ваша команда 'awk' добавляет новую строку после каждой существующей строки и мусор последней строки '*** abc123 ~'. – user3439894

1

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

sed 's/[^*~]\+/abc123/4' file 

Заменить четвертое появление чего-то, которое не содержит ~ или ее * с abc123.

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