2015-02-17 3 views
1

Привет, У меня есть файл, который мне нужно добавить в формат, который я могу извлечь в таблицу Excel. Я не знаю, как это сделать, и я был бы признателен, если бы вы могли мне помочь.Форматирование текста Awk Sed

Вот входной образец

#1 

Indiana University—​Bloomington (Kelley) 
Bloomington, IN 

90 58 82 86 
#1 

Temple University (Fox) 
Philadelphia, PA 

95 66 97 95 
#1 

University of North Carolina—​Chapel Hill (Kenan-​Flagler) 
Chapel Hill, NC 

73 58 100  75 
#4 

Здесь выход

#1, Indiana University—​Bloomington (Kelley) Bloomington, IN, 90, 58, 82, 86, 
#1, Temple University (Fox) Philadelphia, PA,   95,  66,  97,  95, 

Я использую сценарии оболочки в Linux

Благодаря

+0

, кстати, это очень плохая идея использовать ',' в качестве разделителя. 'Филадельфия, PA' содержит', ', поэтому везде, где вы используете этот файл, вы будете иметь непредвиденные последствия. –

+0

Спасибо, что это работает. Благодарен за быстрый ответ сообщества. – matthewthegreat

ответ

3

Это довольно просто с GNU awk и mawk, если вы не пытаетесь использовать его линейным способом. Мы будем использовать # в начале строки как разделитель записей и новую строку как разделитель полей. Тогда:

awk -v RS='(^|\n)#' -F'\n' 'NR > 1 { gsub(/ +/, ", ", $6); print "#" $1 ", " $3 " " $4 ", " $6 }' filename 

То есть:

NR > 1 {        # the first record is the empty bit before 
             # the first separator, so we skip it 
    gsub(/ +/, ", ", $6)    # then: insert commas in the number row 
    print "#" $1 ", " $3 " " $4 ", " $6 # and reassemble the record in the right 
             # format for printing. 
} 

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

+0

Nice :) Спасибо, что дал ответ 'awk' (хорошо,' gawk', но кто в BSD ад использует что-нибудь еще?). Кроме того, вы даете хороший пример того, почему использование 'awk' может быть не самым простым подходом во все времена, но часто там * - это элегантное решение, подобное вашему. Престижность! –

+0

@ MarcusMüller Я видел коробки, у которых был только mawk, и есть некоторые особенности gawk, которые mawk не понимает (особенно «ENDFILE», что вызвало у меня некоторое горе). К счастью, mawk понимает регулярное выражение 'RS', а другие awks редки в эти дни. – Wintermute

+0

:) Я просто отказался от чего-то, кроме 'grep -e' и' sed', теперь именно по этой причине - вы стараетесь быть как можно более универсальным (т. Е. Уважать системы, в которых интерпретаторы языка сценариев не являются доступно), но вы в конечном итоге исправляете свои скрипты, чтобы фактически работать со странными вещами, с которыми вы сталкиваетесь.И затем, кто-то бросает пути Windows в ваш скрипт, и все врывается в огонь. Ах - чуть не забыл ответить на ваш ответ :) –

0

Хотя это вполне возможно, что вы можете сделайте это с небольшим количеством скриптов awk, я бы порекомендовал вас не делайте этого.

Фактически, awk удобен для всего, что не слишком сложно, но здесь, поскольку вы уже планируете использовать Excel, вы можете просто импортировать простой файл, а затем обработать его в excel, pivoting, reshaping, разбивая его там.

Однако я ненавижу Excels сложность, так вот мой python2 подход (сохранив его как program.py и сделать его исполняемым, как chmod 755 program.py):

#!/usr/bin/python 
import sys 

wholefile = open(sys.argv[1], "r").read() 
parts = wholefile.split("#") 

for item in parts: 
    lines = item.split("\n") 
    output = [ int(lines[0]), lines[2], lines[3],lines[5].split() ] 
    print ";".join(output) 

и запустить это как

program.py input.txt > output.csv 

EDIT : typo, и:

Я обычно говорю это слишком часто, но что-то делаю в скорлупе sc ript, который не очень сосредоточен на желании вызвать много команд, часто намного менее эффективен, чем использование любого языка сценариев общего назначения. Python настолько обилен повсюду, что я редко нахожу себя в написании сценариев bash.

EDIT2: Хорошо, поэтому нет пула на вашем хосте. страшный; Использовать bash встроенная функция read (man read).

+0

Thx, но я не могу использовать python, который не поддерживается на хосте. – matthewthegreat

+0

Хорошо, это искры моего интереса: какой уважающий себя хозяин дает вам доступ к оболочке bash и всем стандартным инструментам GNU, но не к python? Есть ли perl, php (ugh), * anything * available? –

+0

Добавлена ​​подсказка для использования 'read' из встроенных функций' bash'; он поддерживает назначение переменных и массивов и может подойдет вашей потребности довольно хорошо, если используется в цикле –

1

Awk сценария, чтобы решить эту проблему:

/^#[0-9]/ {current = $0} 

/\([A-Za-z ]+\)/ { current = current "," $0} 

/[A-Z]+$/ { current = current $0} 

/^[0-9]+/ {current = current "," $1 "," $2 "," $3 "," $4; print current} 

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

cat yourdatafile | awk -f script.awk > output.csv 

Объяснение:

Каждый из регулярных выражений соответствуют шаблонам на разных линиях и выполняет действие для этого рядом с регулярным выражением.

  • Для # номера, инициализируйте/перезапишите текущую переменную # номером.
  • Для текста информации без государства, добавить его к текущей переменной с запятой в начале
  • Для текста информации с государством, добавить его к текущей переменной без запятой в начале
  • Для список номеров, добавить их к текущей переменной с запятой в начале и между каждым затем распечатать текущую переменную
+0

Это также очень помогает вам. – matthewthegreat

0
sed '#n;/[0-9 ]/ s/ */, /g;/^ *$/d;H;$!b;g;s/.//;s/\n\([^#]\)/, \1/g;p' YourFile 
  • удалить и запись предварительно отформатированные строки
  • провести оставшиеся данные
  • в конце, загрузите буфер
  • удалить первый символ новой строки
  • заменить любую новую строку, не сопровождаемый # по , и последовавший обугливается себя
  • распечатать результат

если последний , является обязательным (не нормально в CSV/Excel файл) адаптировать /[0-9 ]/ s/ */, /g с этим ;/[0-9 ]/ {s/ */, /g; s/$/,/;}

0

Вот альтернативный способ сделать это с AWK лишь манипулируя выходной разделитель полей (OFS) и выходной разделитель записей (ORS):

grep -v '^$' infile |  # remove empty lines 
awk 'NR%4 { ORS=", "; OFS=" " } NR%4 == 0 { ORS="\n"; OFS=", " } $1=$1' 

Выход:

#1, Indiana University—​Bloomington (Kelley), Bloomington, IN, 90, 58, 82, 86 
#1, Temple University (Fox), Philadelphia, PA, 95, 66, 97, 95 
#1, University of North Carolina—​Chapel Hill (Kenan-​Flagler), Chapel Hill, NC, 73, 58, 100, 75 
#4,