2013-12-19 3 views
3

Я бы, хотя это была бы простая задача, но нет!Отделить все символы строки от FS (awk)

вход (труба разделителей):

record1|ABCDEFGH 
record2|IJKLMNOP 

Я бы нужен этот вывод:

record1|A|B|C|D|E|F|G|H 
record2|I|J|K|L|M|N|O|P 

То, что я пытался до сих пор:

awk 'BEGIN{FS=OFS="|"}{a = split($2, b, ""); for(i=1; i<=a; i++){printf("%s|%s, $1, b[i](i==a? "\n":"|"))}}' input 

и я получаю:

record1|A 
record1|B 
record1|C 
... 

Я не понимаю! Если бы кто-нибудь мог мне это объяснить ...

ответ

3

Ваш printf s находится на всем протяжении магазина. С изменениями, как показано ниже, она работает, как ожидалось

awk 'BEGIN{FS=OFS="|"}{a = split($2, b, ""); 
    printf "%s|", $1; 
    for(i=1; i<=a; i++){printf("%s%s", b[i],i==a? "\n":"|")}}' input 
+0

Спасибо 1_CR! Я понятия не имел, что мы можем разделить 'printf' для каждого поля. Это гораздо более гибко, чем я, хотя на самом деле. – lqdo2000

2

В этом коде вам не нужно будет OFS и IFS определяются с помощью -F переключателя.

awk -F "|" '{split($2,b,"");printf("%s",$1);for(i=1;i<=length($2);i++) printf("|%c",b[i]);printf("\n")}' input 

Или, если вы предпочитаете не использовать дополнительную переменную Ь и раскол в пользу использования SUBSTR(), код можно записать в виде.

awk -F "|" '{printf("%s",$1);for(i=1;i<=length($2);i++) printf("|%c",substr($2,i,1));printf("\n")}' input 
+1

Я думаю, вы имеете в виду 'FS'. 'IFS' - это bash-ism. – Steve

+1

Thanks user3088572! Он работает очень хорошо. – lqdo2000

+0

@Steve - да, вы правы. Я имел в виду FS, но написал IFS. Мне не нужно обновлять свой ответ, поскольку вы уже предоставили лучшее решение. – alvits

6

Вот еще один способ использования awk:

awk -F '|' '{ gsub(/./, FS "&", $2) }1' OFS= file 

Результаты:

record1|A|B|C|D|E|F|G|H 
record2|I|J|K|L|M|N|O|P 
+0

Спасибо Стив! Этот способ проще, действительно не думал о подстановках. – lqdo2000

+0

+1 Я бы сказал, что это лучшее решение. Для удобства чтения, возможно, мы можем переместить OFS внутрь и использовать печать вместо 1. awk -F "|" 'BEGIN {OFS = //} {gsub (/./, FS "&", $ 2); print}' input – alvits

+0

@ user3088572: Спасибо, но я не согласен, что это улучшает читаемость. Если вы хотите использовать блок «BEGIN», было бы лучше также определить ваш «FS» там, а не использовать его в сочетании с флагом «-F». И 'OFS = //' лучше писать как 'OFS =" "'. Кроме того, гораздо более awkish/perly просто возвращает true, чем использовать инструкцию 'print'. – Steve

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