разделение столбца в Bash на основе '_'

В зависимости от используемых инструментов и используемой файловой системы могут быть различия.

С точки зрения приложения fallocateсоздаваемые файлы обычно заполнены нулями; ваше время измерения будет искажено, и на него еще больше повлияет, если вы используете протоколы или файловые системы со встроенным сжатием или дедупликацией -, поскольку объем передаваемых/записываемых данных никогда не будет отражать те же операции с эквивалентный файл того же размера, созданный другими средствами.

Кроме того, как правильно Stéphane Chazelas указывает, файлы отображаются как содержащие 0, потому что экстенты помечены как "незаписанные". При их чтении система возвращает 0, даже не читая диск.

Было бы предпочтительнее использовать либо файлы.txt, либо, что еще лучше, файлы, созданные из случайных двоичных данных.

0
20.09.2019, 04:38
3 ответа

Я бы использовал:

awk -F' *_?' '{ print $(NF-1), $NF }' infile
0
28.01.2020, 03:16

Вам это подходит? Я приму этот формат:

A B C post_id
a,b,c,86680728811_272953252761568
a,b,c, 86680728811_273859942672742
a,b,c,86680728811_281125741936891
a,b,c,86680728811_10150500662053812
a,b,c,_86680728811_10150500969563812
a,b,c,86680728811_10150501303143812
a,b,c,86680728811_305275689511038
a,b,c,_86680728811_10150501624593812
a,b,c, 86680728811_10150501873973812
a,b,c,86680728811_145945585518261

Затем команды

cat file | sed -Ee 's/(.*)post_id/\1page ID post I/' -e 's/,[_ ]/,/' -e 's/_/,/'

Выход:

A B C page ID post ID
a,b,c,86680728811,272953252761568
a,b,c,86680728811,273859942672742
a,b,c,86680728811,281125741936891
a,b,c,86680728811,10150500662053812
a,b,c,86680728811,10150500969563812
a,b,c,86680728811,10150501303143812
a,b,c,86680728811,305275689511038
a,b,c,86680728811,10150501624593812
a,b,c,86680728811,10150501873973812
a,b,c,86680728811,145945585518261

-Eиспользовать расширенные регулярные выражения (GNU ), чтобы можно было захватывать группы.


Измените заголовок, чтобы добавить page ID post IDзахват первой группы (.*)до post_idи замену ее захваченной группой \1и page ID post ID

.
's/(.*)post_id/\1page ID post ID/'

Удалите начальные пробелы и знак подчеркивания _из строк после запятой и замените их одной запятой.

sed 's/,[_ ]/,/'

Наконец, замените символы подчеркивания _запятой.

sed 's/_/,/'

Остерегайтесь, что я удалил команду cut, которой не должно было быть там (это было напоминание о других командах, которые я пробовал)

0
28.01.2020, 03:16
awk -F', *_?' -v OFS=, '
  NR==1 {
    for (i=1;i<=NF;i++) {
      if ($i == "post_id") {
        $i = "page ID" OFS "post ID";
        col=$1;
      };
    };
    print;
    next
  };

  {
    split($col,a,/_/);
    $col=a[1] OFS a[2];
    print;
  };
  ' FB_Dataset.csv

Поскольку данные поля, которые вы показали, имеют несовместимый формат (некоторые с начальными пробелами, некоторые начинаются с подчеркивания, возможно, некоторые с обоими ), этот awkскрипт использует регулярное выражение, *_?(" запятая, за которой следует ноль -или -пробелов и, возможно, символ подчеркивания" )в качестве разделителя полей(FS).

Он также устанавливает разделитель полей вывода(OFS)в виде запятой.

При чтении ввода он обрабатывает первую строку (, заголовки CSV )и все остальные строки по-разному:

Для первой строки(NR==1)он проверяет значения каждого поля в поисках строки "post_id". Если он находит эту строку, он изменяет значение этого поля, чтобы оно имело два новых имени поля(page IDи post ID), разделенных OFS. Он также сохраняет порядковый номер этого поля в переменной colдля последующего использования. Наконец, он печатает измененную строку.

Предполагается, что имена полей уникальны, как и должно быть для действительных файлов CSV. Это не будет работать правильно, если более одного поля имеют имя post_id.

Для остальных строк поле $colразбивается на массив a, используя символы подчеркивания(_)в качестве разделителя.Затем он заменяет $col первыми двумя элементами этого массива, разделенными OFS. Затем он печатает измененную строку.

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

A,B,C,post_id,D,E,F
a,b,c,86680728811_272953252761568,d,e,f
a,b,c, 86680728811_273859942672742,d,e,f
a,b,c,86680728811_281125741936891,d,e,f

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

A,B,C,page ID,post ID,D,E,F
a,b,c,86680728811,272953252761568,d,e,f
a,b,c,86680728811,273859942672742,d,e,f
a,b,c,86680728811,281125741936891,d,e,f

В строке заголовка поле post_idбыло преобразовано в два поля(page IDи post ID), а в данных CSV соответствующее поле было разделено на два поля.

Кстати, поскольку скрипт ищет совпадающее имя поля(post_id)в строке заголовка, он будет работать с любым количеством полей до и/или после поля, которое мы хотим разделить. В этом образце данных было обнаружено, что четвертое поле содержит нужное нам имя, поэтомуcol=4


Обратите внимание, что $iи $colв awk не означают одно и то же, что и в оболочке.

  • В оболочке они будут означать переменные, чьи имена равны iи col.
  • В awkони означают «значение поля, порядковый номер которого равен значению переменнойi(или переменной col)». то есть это доступ к полю через косвенность.

    напр. если i=1, то $iозначает «значение в поле 1», что совпадает с $1.

    Это полезно, если, например, вам нужно выполнить арифметические действия над номером поля. В awk NF— это автоматически -созданная переменная, содержащая порядковый номер последнего поля текущей входной строки. поэтому $NFозначает «значение в последнем поле», а $(NF-1)означает «значение во втором -последнем поле» и так далее.

1
28.01.2020, 03:16

Теги

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