2014-10-08 6 views
1

У меня есть файл с разделителями табуляции с тремя столбцами. Каждая строка в третьем столбце содержит строку с 4 именами, каждая из которых разделена пробелом (''), но в некоторых случаях между именами имеется более одного пространства. Я хотел бы использовать командную строку unix-bash для печати столбца 1, столбец 2, name1, name2, name3, name4, name5, все разделенные вкладкой.unix bash: разделение определенного столбца на несколько столбцов

Мой желаемый результат будет выглядеть следующим образом:

avov2323[tab]rogoc232[tab]Roy[tab]Don[tab]Mike[tab]Ned[tab]Lee 
cdso3432[tab]fokfd543[tab]Tom[tab]Gil[tab]Rose[tab]Dan[tab]Sam 
  • Есть ли способ хранить все мои колонки 3 в переменную, а затем разделить этот конкретный переменной на основе пространств? что-то вроде: a = awk -F "\t" '{print $3}' file.txt; awk -F "" '{print $ 1}' $ a;

хотя - эта командная строка не работает для меня ... так как все имена из столбца 3 тесно связаны друг с другом в $ a.

+0

Просьба показать образцы входных данных .. с ** и ** без каких-либо незначительных пробелов! –

ответ

3

Использование tr перевести:

tr <inputFile " " "\t" | tr -s "\t" >outputFile 

Edit: Как Гленн Джекман отметил, что было бы лучше, чтобы первые сжимания пространства, а затем изменить остальные пробелы для вкладок.

tr <inputFile -s " " | tr " " "\t" >outputFile 

Он по-прежнему уязвим для пробелов в первых двух столбцах.

+0

учтите мое издание на вопрос (в некоторых случаях между именами имеется более одного пространства) – Roy

+0

Да, вы правы. Я пропустил это. Я адаптировал моего маленького монстра. –

+1

+1 Мне это нравится. Один риск: сжать вкладки взорвутся, когда есть пустые поля. Сначала вы можете сначала сжать пробелы, а затем перевести пробелы на вкладки –

1

Вы можете использовать AWK:

$ cat file 
avov2323  rogoc232  Roy Don Mike Ned Lee 
cdso3432  fokfd543  Tom Gil Rose Dan Sam 
$ awk '{$1=$1}1' OFS='\t' file 
avov2323  rogoc232  Roy  Don  Mike Ned  Lee 
cdso3432  fokfd543  Tom  Gil  Rose Dan  Sam 

$1=$1 просто затрагивает каждую запись так применяется новый формат вывода. 1 оценивает значение true, поэтому каждая строка печатается. Awk обрабатывает любое количество пробельных символов в качестве разделителя полей ввода, так как вы можете видеть, количество пробелов между каждым именем не является проблемой.

Для перезаписи исходного файла, вы можете использовать временный файл:

awk '{$1=$1}1' OFS='\t' file > tmp && mv tmp file 
+0

благодарит миллион! - Это очень хорошо для меня. – Roy

+0

Еще проще: 'awk -v OFS = '\ t' '$ 1 = $ 1''. Вы можете проверить результат с помощью 'echo -e avov2323 \\ trogoc232 \\ tRoy Don Mike Ned Lee | awk -v OFS = '\ t' '$ 1 = $ 1' | od -c' –

+0

@Vytenis единственным потенциальным недостатком использования '$ 1 = $ 1' является то, что когда первый столбец оценивается как false (например, он равен« 0 »), строка не будет напечатана. Например, 'awk '$ 1 = $ 1' <<<" 0 "' ничего не печатает. В этом случае это, похоже, не проблема. –

1

Просто для полноты картины, я также написал AWK Oneliner, который не будет касаться каких-либо пробелов в первых двух столбцах. Он также сохраняет пустые столбцы:

awk <inputFile -F '\t' 'BEGIN{OFS="\t"} {gsub(/ +/,OFS,$3); print $1,$2,$3}' 

Edit: Что касается улучшения упомянутого в комментарии - да, можно разделить любой столбец, даже средний, хотя более универсальный сценарий будет необходимо. Однако это не oneliner и выглядит довольно неудобно, если поставить его в одну строку. Я уверен, что он все еще может быть несколько оптимизирован. При форматировании:

BEGIN { 
    FS=OFS="\t"; 
    splitAt=3; 
}{ 
    gsub(/ +/,OFS,$splitAt); 
    line=$1; 
    for(i=2;i<splitAt;i++) 
    line=line""OFS""$i; 
    line=line""OFS""$splitAt; 
    for(i=splitAt+1;i<=NF;i++) 
    line=line""OFS""$i; 
    print line; 
} 

И в заряде:

awk <inputFile 'BEGIN{FS=OFS="\t"; splitAt=2;} {gsub(/ +/,OFS,$splitAt); line=$1; for(i=2;i<splitAt;i++) line=line""OFS""$i; line=line""OFS""$splitAt; for(i=splitAt+1;i<=NF;i++) line=line""OFS""$i; print line ;}' 

Может быть переработан, чтобы обеспечить splitAt в качестве параметра сценария.

+0

Hi Krzysztof, Ваше решение хорошо работает! - но что, если мне нужно будет разбивать на основе пробелов не мой третий столбец, а мой 35-й столбец, а затем напечатать все столбцы с разделителями табуляций от 1 до 35, включая только что сформированные столбцы, которые были вложены (по пробелам) в 35-й столбец? ... есть способ включить это в вашу команду, а не утомительно напечатать в конце:; print $ 1, $ 2, $ 3, $ 4, .. и т. д., $ 35} '?? большое спасибо! – Roy

+0

Хорошо, решение для моего вопроса на самом деле это: awk -F '\ t' 'НАЧАТЬ {OFS = "\ t"} {gsub (/ + /, "\ t", $ 35); for (i = 1; i <= 35; i ++) printf "% s", $ i "\ t"; printf "\ n"} 'aaa.txt> mine.txt – Roy

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