Переупорядочить столбцы, разделенные : в LINUX

¿Podría ser un problema de firewall? Ha sido un tiempo para mí en sendmail.

Podría probar telnet {ip} 25

Verifique el resultado.

1
14.05.2019, 08:14
2 ответа

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

Ваша попытка 1

Ваша команда awkпытается разбить ваши строки на вхождения admin:. Даже если бы это имело смысл, вы могли бы ссылаться только на поля $1и $2, поскольку у вас есть только одно вхождение admin:в каждой из ваших строк.

Возможно, вы ищете что-то вроде:

printf '%s\n' '"_id":"asc","name":"enygren","admin":[],"creat":"date3"' |
  sed 's/"//g' |
  awk -F',' -v OFS='|' '{if ($2~/name:/){print $1,$3,$4,$2} else {$1=$1; print $0}}'

Что, конечно, может оказаться не очень хорошей идеей.:/name:/соответствует всему, что содержит name:, а не только точную метку name:.

В любом случае, это похоже на задачу XY .


Изменение порядка столбцов

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

Предполагается, что поля ваших входных данных не могут содержать никаких "или ,. Это звучит разумно, основываясь на коде, который вы разместили 1 , но на самом деле это не так. Вам следует прибегнуть к некоторому инструменту, специализирующемуся на манипулировании структурированными данными (, см. ниже ), например. csvkit для CSV или jq для JSON (спасибо Kiwi за подсказку ).

Учитывая сценарийprog_file:

BEGIN {
                        # Create an array of labels for the fileds you want
                        # to keep, in the order you want to print them
    labels[1] = "\"_id\""
    labels[2] = "\"admin\""
    labels[3] = "\"creat\""
    labels[4] = "\"name\""
}
{
                        # Split any field on ":" and make an array of
                        # full fields indexed by their label.
                        # This assumes labels DO NOT CONTAIN any ":"
    for ( i=1; i<=NF; i++ ) {
        split($i, chunks, ":")
        fields[chunks[1]] = $i
    }
                        # Reset the record
    $0 = ""
                        # Re-build the record with only the fields
                        # whose labels are in the array we defined in
                        # the BEGIN block.
                        # Explicitly use "4" as the upper bound because
                        # POSIX does not specify the order in which
                        # "for (var in array)" assigns indexes to var
    for ( i=1; i<=4; i++ ) {
        $i = fields[labels[i]]
    }
                        # Strip any double quote
    gsub("\"","")
    print $0
}

и вход 2:

"_id":"123","admin":[src],"creat":"date1","name":"dedu"
"_id":"2w3","admin":[analise],"creat":"date2","name":"csv"
"_id":"asc","name":"enygren","admin":[],"creat":"date3"
"_id":"scd","admin":[],"creat":"date4","name":"tzpi"

призыв:

awk -v FS=',' -v OFS='|' -f prog_file input_file

дает 3:

_id:123|admin:[src]|creat:date1|name:dedu
_id:2w3|admin:[analise]|creat:date2|name:csv
_id:asc|admin:[]|creat:date3|name:enygren
_id:scd|admin:[]|creat:date4|name:tzpi

Работа с форматами данных

Последняя выборка входных данных, которую вы отредактировали в своем вопросе, похоже, не из текстового файла с разделителями. Это похоже на список объектов JSON.
Несмотря на то, что он -удобочитаем для человека, JSON представляет собой формат данных и требует другого подхода — действительно, приведенное выше awkрешение не будет работать с такими входными данными.

Добавив битовую структуру, ваш семпл можно повернуть (назад?)в действительный JSON:

$ cat file
"a":"val1","c":"val2","b":"val3","d":"val4"
"a":"val1","b":[],"c":"val3","d":"val4"
"a":"val1","d":["val2","val32"],"c":"val3","b":"val4"
"d":"val1","a":"val2","c":"val3","b":"val4"

(Обратите внимание, что я предположил, что отсутствующий "в "d":["val2","val32]был опечаткой, и использовал "d":["val2","val32"]вместо ).

$ sed 's/^/{/; s/$/},/; 1 s/^/[/; $ s/,$/]/' file >tmpfile
$ cat tmpfile 
[{"a":"val1","c":"val2","b":"val3","d":"val4"},
{"a":"val1","b":[],"c":"val3","d":"val4"},
{"a":"val1","d":["val2","val32"],"c":"val3","b":"val4"},
{"d":"val1","a":"val2","c":"val3","b":"val4"}]

Тогда безопасным подходом будет использование процессора JSON в качестве jqдля фильтрации и изменения порядка ваших данных:

$ jq -r '.[] | {a:.a, b:.b, c:.c, d:.d} | @text' tmpfile
{"a":"val1","b":"val3","c":"val2","d":"val4"}
{"a":"val1","b":[],"c":"val3","d":"val4"}
{"a":"val1","b":"val4","c":"val3","d":["val2","val32"]}
{"a":"val2","b":"val4","c":"val3","d":"val1"}

Удаление оставшихся открывающих и закрывающих фигурных скобок тривиально и безопасно, в то время как будет небезопасно слепо удалять двойные кавычки(")или заменять запятые вертикальными чертами(,|)для полностью соответствует выходному образцу.


1Из вопросов исправлений № 4 по № 7 .
2Вывод из последней части вопроса редакция № 6 .
3Из вопроса редакция № 6 .

2
27.01.2020, 23:30

Извините, если я проигнорирую вашу попытку. Мне это кажется слишком сложным, поскольку требует множества скриптов и инструментов.

Насколько я понимаю, столбцы расположены в правильном порядке, за исключением idxg_name, который должен стоять в конце. Поэтому я предлагаю просто сделать:

sed 's/"//g;s/\(,idxg_name:[^,]*\)\(.*\)/\2\1/' yourfile
  • Часть s/"//gудаляет ", как вы уже делали
  • ,idxg_name:[^,]*соответствует полю idxg_name, начиная с запятой и включая все до следующей запятой (обратите внимание, что это не удастся, если имя содержит запятую! Если это может произойти, это усложнит ситуацию, учитывая,находится ли запятая внутри"")
  • .*соответствует остальной части строки и
  • замена \2\1изменяет порядок обеих частей внутри этих \(\), помещая таким образом поле имени в конец строки. Сделанный.
0
27.01.2020, 23:30

Теги

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