Изменение последних записей в списке через запятую


8

У меня есть огромный текстовый файл, который выглядит так:

36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,3
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,8
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,14
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,12

Желаемый вывод это:

36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-03
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-08
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-14
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,MI-12

Я пробовал другие соответствующие посты здесь и в других сообществах, но не смог точно получить то, что хочу.

ОБНОВИТЬ

Это перекрестный вопрос (для этого мне нужны и ответы Unix / Perl, и пакетные решения / PowerShell.), У которого есть интересные ответы.

Ответы:


14

Подход awk сфункцией sprintf (для добавления ведущих нулей):

awk -F, -v OFS=',' '$8=sprintf("MI-%02d",$8);' file

Выход:

36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-03
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-08
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-14
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,MI-12

-F,- установить запятую ,как разделитель полей

$8 - указывает на восьмое поле

%02d- формат, который обрабатывает аргумент функции как 2- значное число


Обратите внимание , что последнее поле в записи может быть представлено$NF.

NF - это предопределенная переменная, значением которой является количество полей в текущей записи

Итак, так $NFже, как $8(для вашего ввода)

awk -F, -v OFS=',' '$(NF)=sprintf("MI-%02d", $(NF))' file

1
Слово предупреждения (не имеет значения в этом примере, но может применяться в других случаях): изменение значения одного из полей (здесь: $ 8) «пересчитывает» поля всей строки и имеет побочные эффекты: ex1: теряет несколько разделителей ': echo "1   2 3    4" | awk '{$2=$2;print $0}'дает: 1 2 3 4(только 1 пробел (или OFS) осталось между полями). ex2) echo "1,,,2,3,,,,4" | awk -F',' '{$2=$2;print $0}'дает: 1   2 3    4(запятые стали пробелами). Могут быть и другие побочные эффекты. Протестируйте и используйте другой подход (например, gsub для переменной копирования $ 0), если назначение поля имеет вредные побочные эффекты.
Оливье Дюлак

3

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

awk 'BEGIN { FS = OFS = "," } { $NF = sprintf("MI-%02d", $NF); } 1' file

2

Вот решение Perl:

$ perl -F',' -lane '$last=$#F;$F[$last]=sprintf("MI-%02d",$F[$last]);print join ",", @F' input.txt                                       
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-03
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-08
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-14
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,MI-12

-aФлаг позволяет рассматривать в качестве входного массива, на основе указанного сепаратора с -F. По сути, мы изменяем последний элемент в этом массиве и перестраиваем его с помощью joinкоманды.


Спасибо за ваш ответ. Это помогает, если кому-то нужен Perl, но все sprintfже это основная идея вашего ответа. Не так, если это не правильно, просто не предлагать что-то другое, чем принятый ответ. +1 в любом случае.
М--

1
@ Хорошо, главная причина здесь в том, что sprintf()обычно используется при записи строки определенного формата в переменную, поэтому она используется во многих других языках. Я также могу написать это на Python - Python не имеет, sprintf()но основная идея будет одинаковой независимо - запись отформатированной строки в переменную. В качестве альтернативы, мы можем напрямую работать с элементами массива и просто печатать их. С этим типом вопросов есть конечное количество решений, в основном это то, что я пытаюсь сказать
Сергей Колодяжный

1

С входными данными, такими как:

36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,3  
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,8  
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,14  
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,12  

в text.csv

код ниже

awk -F"," '{ i = 0;
  MyOutLine = "";
  j = NF - 1;
  while ( i < j ) {
    i++;
    MyOutLine = MyOutLine""$i",";
  }
  i++;
  x = sprintf( "%.2i", $i );
  y = "MI-"x;
  MyOutLine = MyOutLine""y;
  print MyOutLine; }' ./text.csv  

производит вывод как:

36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-03
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-08
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-14
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,MI-12

1

Tcl

Вот мое решение, выполненное с использованием Tcl, который читает из файла input.csv и помещает результат в файл output.csv

set in [open input.csv]
set out [open output.csv w]

while {![eof $in]} {
   set line [gets $in]
   set last_comma_pos [string last , $line]
   puts $out [string range $line 0 $last_comma_pos][format MI-%02d [string range $line $last_comma_pos+1 end]]
}

close $in
close $out

демонстрация

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.