Как разделить поле в CSV и дублировать поля в строке в новую строку

Muchas gracias a @GAD3R

Aunque su script no funcionó para mí, lo modifiqué ligeramente para que lo hiciera.

Mi máquina no pudo leer nada de /sys/class/net/wlan0/carrier, así que usé greppara leer de ip ay determinar a partir de ahí si el estado debe cambiarse a 'arriba' o 'abajo'.

Además de esto; También usé zenitypara mostrar una notificación en pantalla -de los cambios que había hecho. El guión terminó luciendo así;

#!/bin/bash


if
ip a | grep -q "wlan0: <BROADCAST,MULTICAST>";

then
ip link set wlan0 up
zenity --notification --text="Wireless state changed to UP"

else
ip link set wlan0 down
zenity --notification --text="Wireless state changed to DOWN"

fi

Luego usé métodos abreviados de teclado para ejecutar este comando al presionar la tecla de acceso rápido.

Gracias de nuevo por cualquier ayuda.

gato

0
30.05.2019, 18:10
4 ответа

Использование GNU Awk(gawk)для запуска foldчерез Getline/Variable/Coprocess

gawk -F, '
  BEGIN{
    OFS=FS; 
    cmd="fold -sw 16";
  }

  # if total length (16 + 2 for quotes) is within limit, print as-is
  length($NF) <= 18 {print; next}

  # else
  {
    # trim the quotes, then fold
    print substr($NF,2,length($NF)-2) |& cmd; 
    close(cmd,"to"); 
    NF--; 
    while((cmd |& getline var) > 0){

      # (optional) trim trailing whitespace
      sub(/[ \t]+$/,"",var);

      print $0, "\"" var "\"" ;
    }
    close(cmd,"from");
  }
' file.csv

subудаляет завершающие пробелы из операции fold.

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

3
28.01.2020, 02:18

Я создал весьма неуклюжий awk-скрипт, сохраняющий двойные кавычки. Вот оно:

{
    for ( i=0; i<= length($6); i+=16 )
    {
        if ( i+17 < length($6) )
        {
            if ( i == 0 )
                printf ("%s,%s,%s,%s,%s,%s\"\n", $1, $2, $3, $4, $5, substr($6,i,16))
            else
                printf ("%s,%s,%s,%s,%s,\"%s\"\n", $1, $2, $3, $4, $5, substr($6,i+1,16))
        }
        else
        {
            if ( i == 0 )
                printf ("%s,%s,%s,%s,%s,%s\n", $1, $2, $3, $4, $5, substr($6,i,16))
            else
                printf ("%s,%s,%s,%s,%s,\"%s\n", $1, $2, $3, $4, $5, substr($6,i+1,16))
        }
    }
}

Вывод:

$ awk -F, -f awks csvfields
"5","4","3","2","1","XYZ ABCD E"
"1","2","3","4","5","AB CDE F GHI JK"
"1","2","3","4","5"," LMNOP Q RS TUV "
"1","2","3","4","5","W XYZ 12 3456 78"
"1","2","3","4","5","90"
"9","8","7","6","5","LMN O PQ R"
$

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

1
28.01.2020, 02:18

Пробовал код ниже, тоже работает нормально

 k=16;for ((j=1;j<=50;j++)); do  awk -v j="$j" -v k="$k" -F "," '{if(length($NF) > 16){print $1,$2,$3,$4,$5,substr($NF,j,k)}else {print $0}}' filename; j=$(($j+16)); done|sort | uniq

выход

"5","4","3","2","1","XYZ ABCD E"
"1","2","3","4","5","AB CDE F GHI JK"
"1","2","3","4","5","LMNOP Q RS TUV W"
"1","2","3","4","5","XYZ 12 3456 7890"
"9","8","7","6","5","LMN O PQ R"
0
28.01.2020, 02:18

Подход, основанный только на SHELL (, протестирован на Bash и Ksh93 ). Однако мне нравится подход fold, так как он использует существующий инструмент.

# read from stdin, output to stdout
# Note no Shebang line at top so it made it easier for to try bash/ksh as interpreters

OIFS="$IFS"
IFS=,
while read f1 f2 f3 f4 f5 f6; do
    f6=${f6#\"}
    f6=${f6%\"}             # strip DQs
    if ((${#f6}<17)); then  # no action
            IFS="$OIFS"
            echo "$f1,$f2,$f3,$f4,$f5,\"$f6\""
            IFS=","
            continue
    else
            IFS="$OIFS"
            while ((${#f6}>17)); do
                    n6=${f6:0:16}
                    f6=${f6#$n6}
                    n6=${n6# }
                    n6=${n6% }
                    echo "$f1,$f2,$f3,$f4,$f5,\"$n6\""
            done
            echo "$f1,$f2,$f3,$f4,$f5,\"${f6# }\""
    fi
    IFS=","
done
IFS="$OIFS"
exit

Результаты:

"5","4","3","2","1","XYZ ABCD E"
"1","2","3","4","5","AB CDE F GHI JK"
"1","2","3","4","5","LMNOP Q RS TUV W"
"1","2","3","4","5","XYZ 12 3456 7890"
"9","8","7","6","5","LMN O PQ R"

Чтобы решить проблему разрыва слов без использования foldили аналогичного, следующий код должен заменить закомментированную строку, показанную ниже в приведенном выше примере. Также замените вторую командную строку echoна :

.
                    c6="$f6"
                    n6=""
                    while (((${#n6}+${#nw})<=16)); do
                            n6=$n6${c6%% *}\
                            n6=${n6# }
                            eval c6=\${c6\#${c6%% *} }
                            nw=${c6%% *}
                    done
                    #n6=${f6:0:16} ### replace by above

и заменить

            echo "$f1,$f2,$f3,$f4,$f5,\"${f6# }\""

с

            ((${#f6}>0)) && echo "$f1,$f2,$f3,$f4,$f5,\"${f6# }\""

, чтобы избежать возникновения каких-либо нулевых остатков поля 6.

Был использован следующий тестовый файл:

"5","4","3","2","1","XYZ ABCD E"
"1","2","3","4","5","AB CDE F GHI JK LMNOP Q RS TUV W XYZ 12 3456 7890"
"9","8","7","6","5","LMN O PQ R"
"1","2","3","4","5","A BB CCC DDD EEEE FFFFF GGGGGG HHHHHHH"

с результатами:

"5","4","3","2","1","XYZ ABCD E"
"1","2","3","4","5","AB CDE F GHI JK"
"1","2","3","4","5","LMNOP Q RS TUV W"
"1","2","3","4","5","XYZ 12 3456 7890"
"9","8","7","6","5","LMN O PQ R"
"1","2","3","4","5","A BB CCC DDD"
"1","2","3","4","5","EEEE FFFFF"
"1","2","3","4","5","GGGGGG HHHHHHH"

Однако использование существующих инструментов, таких как fold, намного проще и соответствует философии UNIX --, основанной на существующих простых инструментах. Но если вам нравится программирование в Shell, то приведенное выше — один из способов получить решение. Если кому-то нужны объяснения кода, пожалуйста, свяжитесь со мной.

0
28.01.2020, 02:18

Теги

Похожие вопросы