Удалить несоответствующие значения из строки в файле с разделителями канала - PullRequest
0 голосов
/ 11 мая 2018

У меня есть входной файл со столбцами, разделенными |

Входной файл:

COL1|COL2
CRIC1|IPL_M1;IPL_M2;TEST_M1
CRIC2|ODI_M1;IPL_M3
CRIC3|ODI_M3;TEST_M5
CRIC4|IPL_M5;ODI_M5;IPL_M;RANGI_M1
CRIC5|RANGI_M1

Выходные данные должны изменяться только в COL2, никакие другие столбцы не должны изменяться, т.е. в COL2строка с IPL_ должна заполняться, кроме IPL_ должна заполняться как ноль и удалять ненужные точки с запятой.COL2 может содержать столько значений (как IPL, так и не IPL)

Ожидаемый результат:

COL1|COL2
CRIC1|IPL_M1;IPL_M2
CRIC2|IPL_M3
CRIC3|
CRIC4|IPL_M5;IPL_M6
CRIC5|

Попробовал это:

awk -F, -vOFS="|" '{$2=($2!="IPL_%")?" ":$2}1' File.txt

Ответы [ 6 ]

0 голосов
/ 12 мая 2018

Другой вариант awk:

awk -F '|' '
    NR == 1 { print; next }
    {
        split($2, a, ";")
        s = ""
        for (i = 1; i <= length(a); ++i)
            if (a[i] ~ /^IPL_/)
                s = s a[i] ";"
        print $1, substr(s, 1, length(s)-1)
    }' OFS='|' file

, который генерирует

COL1|COL2
CRIC1|IPL_M1;IPL_M2
CRIC2|IPL_M3
CRIC3|
CRIC4|IPL_M5;IPL_M
CRIC5|
0 голосов
/ 11 мая 2018

С седом

sed -E '
  1b
  s/\|/\|;/
  s/IPL_M/@/g
  s/;[^@][^;]*//g
  s/\|;/\|/
  s/@/IPL_M/g
' infile
0 голосов
/ 11 мая 2018

Если perl в порядке:

$ perl -F'\|' -lane '$F[1] = join ";", grep {/IPL_/} split /;/,$F[1] if $.>1;
                     print join "|", @F' ip.txt
COL1|COL2
CRIC1|IPL_M1;IPL_M2
CRIC2|IPL_M3
CRIC3|
CRIC4|IPL_M5;IPL_M
CRIC5|
  • -F'\|' -lane Подробнее см. perldoc .Здесь | устанавливается как разделитель входного поля, и результаты доступны из @F array
  • if $.>1, если номер строки ввода больше чем 1
    • split /;/,$F[1], разделить второй входполе ;
    • grep {/IPL_/} фильтрует только элементы, содержащие IPL_ из разделенного вывода.При необходимости используйте привязки регулярных выражений
    • join ";", используйте ;, чтобы объединить выходные данные grep, а затем сохраните результаты обратно во второй элемент @F array
  • print join "|", @F и затем печатать элементы массива @F с | в качестве разделителя
0 голосов
/ 11 мая 2018
$ awk '
    BEGIN { FS=OFS="|"; sfs=";" }
    NR>1 {
        n = split($2,f,sfs)
        $2 = ""
        for (i=1; i<=n; i++) {
            if (f[i] ~ /^IPL_/) {
                $2 = ($2=="" ? "" : $2 sfs) f[i]
            }
        }
    }
    { print }
' file
COL1|COL2
CRIC1|IPL_M1;IPL_M2
CRIC2|IPL_M3
CRIC3|
CRIC4|IPL_M5;IPL_M
CRIC5|
0 голосов
/ 11 мая 2018

Поскольку все классные ответы на awk уже были приняты, я начал играть с PCRE lookaround, поэтому, если вы можете использовать perl, вот что для этого:

perl -p -e 's/(?<=(\|)|(;))[^I][^P][^L][^;\n]*(;|(\n))|/\4/g if $.>1;s/;$//' file
COL1|COL2
CRIC1|IPL_M1;IPL_M2
CRIC2|IPL_M3
CRIC3|
CRIC4|IPL_M5;IPL_M
CRIC5|

Редактировать: Тестирование немного с более чем 3 строки (FO):

$ cat foo
COL1|COL2
CRIC1|IPL_M1;IPL_M2;TEST_M1;FO;FO
CRIC2|ODI_M1;IPL_M3;FO;FO
CRIC3|FO;ODI_M3;TEST_M5
CRIC4|FO;IPL_M5;FO;ODI_M5;IPL_M;RANGI_M1
CRIC5|FO;RANGI_M1

вывод

COL1|COL2
CRIC1|IPL_M1;IPL_M2
CRIC2|IPL_M3
CRIC3|
CRIC4|IPL_M           # fails if <3 preceeds a match 
CRIC5|

Так что да, это не удается.Кажется, это работает немного лучше (изменено на: [^I;\n][^P;\n]?[^L;\n]?):

$ perl -p -e 's/(?<=(\|)|(;))[^I;\n][^P;\n]?[^L;\n]?[^;\n]*(;|(\n))|/\4/g 
  if $.>1;
  s/;$//' foo

$ awk '
BEGIN{ FS=OFS="|" } 
{
    n=split($2,a,";")
    for(i=1;i<=n;i++)
        if(a[i]~/^IPL/||NR==1)
            b=b (b==""?"":";") a[i]
    print $1,b;b=""
}' file

выходы:

COL1|COL2
CRIC1|IPL_M1;IPL_M2
CRIC2|IPL_M3
CRIC3|
CRIC4|IPL_M5;IPL_M
CRIC5|

0 голосов
/ 11 мая 2018

Awk решение:

awk 'BEGIN{ FS = OFS = "|" }
     NR == 1;
     NR > 1{
         len = split($2, a, ";");
         res = "";
         for (i = 1; i <= len; i++)
             if (a[i] ~ /^IPL_/) res = res (res != ""? ";" : "") a[i];
         print $1, res
     }' file.txt

Выход:

COL1|COL2
CRIC1|IPL_M1;IPL_M2
CRIC2|IPL_M3
CRIC3|
CRIC4|IPL_M5;IPL_M
CRIC5|
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...