Как уменьшить количество разделителей, используя sed или awk

У меня есть данные, которые должны быть 30 столбцов в каждой строке. Экспорт не выполняется идеально, и я иногда получаю 32 - 50 столбцов, потому что в самих полях есть дополнительные разделители табуляции.

Мне также нужно удалить запятые из моих тысяч с помощью следующей программы sed.

sed '/[0-9],[0-9]./ {s/,//g; }' $oldfile > $newfile

Итак, как мне преобразовать следующие данные, исключив запятые и добавив дополнительный разделитель в последний столбец?

вот мой пример ввода:

Column1 Column2 Column3
James   1,203.33    comment1
Mike    -3,434.09   testing testing 123
Sarah   1,343,342.23    there   here

Я хотел бы вывод:

Column 1    Column2 Column3
James   1203.33 comment1
Mike    -3434.09    testing_tab_testing_tab_123
Sarah   1343342.23  there_tab_here

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

Я надеялся, что смогу сделать это в sed (на котором я новичок) или awk (я не знаю awk на всех), потому что sed действительно быстро обрабатывает все это.

Изменить: это то, что в конечном итоге работает лучше всего в моей ситуации

sed '/[0-9],[0-9]./ {s/,//g; };s/\t/_tab_/3g' input_file

Сначала он удаляет все запятые между двумя числами. Затем он заменяет мои вкладки на "вкладку" после третьего появления. Я проверю это на работе.

Мое рассуждение о том, что я не использую perl, заключается в том, что мои ограниченные знания об этом заставляют меня верить, что для его оценки потребуется загрузить документ в память, а объем этих документов варьируется от 5 до 30 ГБ, что обычно превышает объем памяти моего компьютера.

Я дам вам знать, если что-то пойдет не так, когда я использую это на работе, но я действительно ценю всю помощь.

3 ответа

Решение

Сложная часть заменяет эти вкладки. Давайте рассмотрим это поэтапно.

Сначала мы пытаемся заменить каждую вкладку на "_tab_";

sed 's/\t/_tab_/g'

Column1_tab_Column2_tab_Column3
James_tab_1,203.33_tab_comment1
Mike_tab_-3,434.09_tab_testing_tab_testing_tab_123
Sarah_tab_1,343,342.23_tab_there_tab_here

(Обратите внимание, что команда содержит "\t", что означает TAB. Не все версии sed допускают это; вам, возможно, придется использовать реальную вкладку.) После того, как у нас это получится, мы можем попробовать заменить вкладки, начиная с третьей. Некоторые версии sed позволяют это:

sed 's/\t/_tab_/3g'

Если ваш sed не позволяет этого, вам, возможно, придется прибегнуть к замене последней вкладки (если их больше двух):

sed 's/\(\t.*\t.*\)\t/\1_tab_/'

(вы можете или не должны избегать скобок с обратными слешами, как я это сделал) и затем повторять эту операцию, пока она не прекратит делать что-либо, с помощью условного перехода к метке:

sed -e :a -e 's/\(\t.*\t.*\)\t/\1_tab_/;t a'

Если вы так или иначе работаете, удаление запятых относительно просто, вы можете просто добавить еще одно предложение в команду:

... -e 's/\([0-9]\),/\1/g'

Вы можете попробовать это awk

awk -F'\t' -v nbcol=3 '
 {a=""
 for(i=1;i<=NF;i++)
   {if($i~/[-0-9+,\.]*/)
     gsub(",","",$i)
   if(i>nbcol)a=a"_"$i}
 $0=$1 FS $2 FS $3 a
}1' infile.txt

-F '\ t' разделитель полей

nbcol=3 столбца для слияния

Строка a = "" для столбца слияния должна быть инициализирована пустой строкой

for(i=1;i<=NF;i++) работают в каждой строке

если ($ я ~/[-0-9+,.]*/) GSUB (" """, $ я)

Если поле является числом, удалите каждый,

если (я>nbcol) = а "_"$ я}

если номер поля больше, чем nbcol, объединить его в строку

$0=$1 FS $2 FS $3 a

в конце каждой строки регенерируйте $ 0 и выведите строку с 1

Удалить запятые, когда они появляются в числе. Я также хочу найти строки с более чем 3(или соответствующим количеством вкладок), а затем заменить вкладки после трех на вкладку

Чтобы удалить запятые, когда они появляются в числе:

sed -E 's/([0-9]+),/\1/g' inputfile

Чтобы заменить три или более вкладок одной вкладкой:

sed -E 's/\t{3,}/\t/g' inputfile

Или примените обе замены в одной команде:

sed -E 's/([0-9]+),/\1/g;s/\t{3,}/\t/g' inputfile

Пример ввода (здесь \t означает вкладку):

Column1 Column2 Column3
James   1,203.33 \t\t\t comment1
Mike    -3,434.09 \t\t testing testing 123
Sarah   1,343,342.23 \t\t\t there   here

Выход:

Column1 Column2 Column3
James   1203.33 \t comment1
Mike    -3434.09 \t\t testing testing 123
Sarah   1343342.23 \t there   here

Изменить: заменить \t с _tab_ для 3-го или более вхождений в данной строке вы можете использовать perl:

perl -pe 's{\t}{++$n >= 3 ? "_tab_" : $&}ge' inputfile

Пример ввода:

Column1 Column2 Column3
James  \t 1,203.33 \t comment1
Mike  \t  -3,434.09 \t testing\ttesting\t123
Sarah  \t 1,343,342.23 \t there\there

Выход:

Column1 Column2 Column3
James  \t 1,203.33 \t comment1
Mike  \t  -3,434.09 \t testing_tab_testing_tab_123
Sarah  \t 1,343,342.23 \t there_tab_here
Другие вопросы по тегам