Удалить столбец, который содержит конкретный текст

Я искал вариант удаления столбца с определенным текстом, например

«ДДД»

aaa bbb ccc ddd eee fff 1 2 3 4 5 6 2 3 4 5 6 0 

Чтобы результат выглядел так:

 aaa bbb ccc eee fff 1 2 3 5 6 2 3 4 6 0 

Я знаю, что есть простой способ удалить столбец 4 и выполнить ту же работу, но мои файлы * .csv не отсортированы. Есть идеи?

4 Solutions collect form web for “Удалить столбец, который содержит конкретный текст”

sed не подходит для этого. Попробуйте awk :

 $ awk -v OFS='\t' 'NR==1{for (i=1;i<=NF;i++)if ($i=="ddd"){n=i-1;m=NF-(i==NF)}} {for(i=1;i<=NF;i+=1+(i==n))printf "%s%s",$i,i==m?ORS:OFS}' file aaa bbb ccc eee fff 1 2 3 5 6 2 3 4 6 0 

Это предполагает, что строка для удаления, ddd в этом случае, появляется как поле в первой строке.

Как это работает

  • -v OFS='\t'

    Это устанавливает разделитель выходного поля на вкладку. Если вы используете что-то еще, измените это.

  • NR==1{for (i=1;i<=NF;i++)if ($i=="ddd"){n=i-1;m=NF-(i==NF)}}

    Это проверяет все столбцы в первой строке. Мы сохраняем номер столбца с ddd (минус один) в переменной n .

    Он также устанавливает m в номер последнего столбца, за исключением случая, когда i является последним столбцом, в этом случае он устанавливает его в NF-1 .

  • for(i=1;i<=NF;i+=1+(i==n))printf "%s%s",$i,i==m?ORS:OFS

    Это выводит каждое поле, пропуская поле, в котором ddd появляется в первой строке.

    i+=1 увеличит i на единицу в каждом цикле. i+=1+(i==n) увеличивает i на единицу в каждом цикле, за исключением случаев, когда i==n в этом случае i увеличивается на 2. Это приводит к пропуску через правый столбец.

    printf "%s%s",$i,i==m?ORS:OFS печатает столбец i за которым следует разделитель столбцов, OFS или разделитель строк ORS , в зависимости от того, является ли i последним столбцом.

Несколько строк

Для тех, кто предпочитает такие команды, написанные на нескольких строках:

 awk -v OFS='\t' ' NR==1{ for (i=1;i<=NF;i++) if ($i=="ddd") { n=i-1 m=NF-(i==NF) } } { for(i=1;i<=NF;i+=1+(i==n)) printf "%s%s",$i,i==m?ORS:OFS } ' file - awk -v OFS='\t' ' NR==1{ for (i=1;i<=NF;i++) if ($i=="ddd") { n=i-1 m=NF-(i==NF) } } { for(i=1;i<=NF;i+=1+(i==n)) printf "%s%s",$i,i==m?ORS:OFS } ' file 

Использование разделенных запятыми файлов

Если мы хотим, чтобы входные данные и выходные данные были разделены запятыми, нам нужно изменить как разделитель входного поля (с -F ), так и разделитель выходного поля. Например, рассмотрим этот входной файл:

 $ cat file2 aaa,bbb,ccc,ddd,eee,fff 1,2,3,4,5,6 2,3,4,5,6,0 

Затем используйте:

 $ awk -F, -v OFS=, 'NR==1{for (i=1;i<=NF;i++)if ($i=="ddd"){n=i-1;m=NF-(i==NF)}} {for(i=1;i<=NF;i+=1+(i==n))printf "%s%s",$i,i==m?ORS:OFS}' file2 aaa,bbb,ccc,eee,fff 1,2,3,5,6 2,3,4,6,0 

Это может быть возможно в sed (большинство вещей), но я сомневаюсь, что это будет проще, чем использование другого инструмента. Самый простой подход – сначала получить нужный номер поля, а затем пройти через файл, распечатывающий остальные. Например, в Perl:

 $ perl -lane 'if($.==1){for(0..$#F){$d=$_ if $F[$_] eq "ddd"}} print "@F[0..$d-1] @F[$d+1..$#F]"' file aaa bbb ccc eee fff 1 2 3 5 6 2 3 4 6 0 

Тем не менее, это затягивает форматирование. Если это важно, используйте вместо этого ответ John1024 .

 #!/bin/bash read -a header <file # read first line into array "header" for i in ${!header[@]} # iterate through array indexes do if [ "${header[i]}" = "ddd" ] # find column equal the pattern then n=$[++i] # put column number in variable "n" break fi done # print all column except found delimited by <TAB> cut --complement -f ${n} < <(tr -s ' ' '\t' <6) 

Но если вам нравится, это может быть сделано «просто sed » (даже это не оптимально)

 sed "s/\S\+\s*//$(sed 's/\s\+/\n/g;1q' file | sed -n '/ddd/=')" file 

\S\+\s* – средний 1 столбец (непространственный символ (ы), который следует за некоторыми возможными пробелами).
s/<pattern>//<number> – Замените только числовое появление шаблона .
s/\s\+/\n/g – Заменить каждое пространство или блок пробелов на \n ewline только для
1q – первая строка (заголовок). Таким образом, его колонка заголовка преобразования преобразуется в строки.
sed -n '/ddd/= – номер строки печати, где существует шаблон == Номер столбца

 awk -F "\t" -v "Pat=ddd" 'NR == 1 {for( i = 1; i <= NF; i++) Take[ i] = (Pat != $i)} {for ( i = 1; i <= NF; i++) if( Take[ i]) printf $i FS; print ""}' YourFile 
  • поле печати, которое не исключается
  • используйте тот же разделитель, что и вход ( -F "\t" )
  • используйте переменную для выбора паттерна для исключения ( -v "Pat=ddd" ). может легко изменяться для выбора регулярных выражений, если много вариантов сделать
  • сделано с помощью 2-х циклов, чтобы избежать путаницы, но может быть сделано только в одном
  • Извлечение данных из текстового файла
  • Найти только сопоставленный шаблон в файле CSV
  • awk или sed или perl: удалять только символы в определенном месте
  • Как найти и заменить содержимое для нескольких файлов в текущем каталоге с помощью сценария оболочки или Linux?
  • Команда SED не заменяет (работает регулярное выражение)
  • Определение средних значений, stdev, stderror и counts значений в списке
  • Добавить кавычки и новый разделитель вокруг слов, разделенных пробелами
  • Заменить многострочную строку в файлах
  • Как удалить часть строки
  • Как добавить текст в конец строки, когда шаблон сопоставлен?
  • как вставить содержимое файла в совпадение с помощью sed - только первое появление
  • Interesting Posts

    Могу ли я реплицировать DNS-записи в формате AXFR, если pdns-recursor находится перед авторитетным pdns

    Отключить автоматическую блокировку экрана в XFCE в Centos

    Разница между смолой и звездой

    Настройки разрешения GRUB2 не соблюдаются Debian – мусор на экране

    Есть ли способ найти файл в обратном рекурсивном поиске?

    Я хочу отправить команды и запросы из клиентского приложения на сервер Linux

    Почему SSH добавляет запись known_host для IP-адреса?

    Найти все размеры и ширину файлов изображений в каталоге

    Есть ли удобный инструмент командной строки для управления заданиями Cron?

    Будет ли использовать производительность воздействия дисплея?

    Что означает эта ошибка python2 и что мне делать с этим?

    Ядро убивает все процессы

    Почему я должен использовать Debian 6 с ядром FreeBSD?

    Пустой файл машинописного текста с командой сценария

    Сделать запуск программы на втором виртуальном рабочем столе (XFCE)

    Linux и Unix - лучшая ОС в мире.