Удалить поля, содержащие определенную строку

Смысл RPROMPT в том, чтобы находиться на той же строке, что и вводимая команда. Я даже не уверен, что вы можете иметь многострочный RPROMPT (разве что включив в него некоторые команды перемещения курсора). Если вам нужна многострочная подсказка с чем-то справа от первых строк, включите это в левую подсказку. Переменная COLUMNS содержит ширину терминала. Вот один из способов сделать это, который использует функцию для перестройки подсказки каждый раз, чтобы получить больше контроля (я не знаю, как добавить к ширине терминала только %; это можно сделать с помощью встроенных подстановок, но это становится трудно читать или расширять):

setopt prompt_subst
precmd_prompt () {
  git_prompt_info=${(r:$((COLUMNS-22)):: :)$(git_prompt_info)}
  PROMPT="[%D{%H:%M:%S}] %>>$git_prompt_info %D{%Y-%m-%d}"
  PROMPT+=$'\n%n@%m:%/\nyes, zoey? : '
}
precmd_functions+=(precmd_prompt)

Если вы хотите еще больше контролировать состав подсказки, создайте ее из нескольких частей. Например, выше я жестко закодировал длину времени и даты. Вот вариант, который вычисляет ширину и соответственно заполняет или усекает среднюю часть, содержащую информацию о git. На этот раз я делаю усечение вручную, чтобы проиллюстрировать, как это можно сделать. ${(%):-STUFF} расширяет последовательности подсказок в STUFF.

precmd_prompt () {
  PS1_1_left=${(%):-'[%D{%H:%M:%S}] '}
  PS1_1_right=${(%):-' %D{%Y-%m-%d'}
  local middle_width=$((COLUMNS-#PS1_1_left-#PS1_1_right}))
  local git_prompt_info=$(git_prompt_info)
  if ((#git_prompt_info < middle_width)); then
    PS1_1_middle=${(r:$middle_width:: :)git_prompt_info}
  else
    PS1_1_middle=${git_prompt_info:0:$middle_width}
  fi
  PROMPT='${PS1_1_left}${PS1_1_middle}${PS1_1_right}'
  PROMPT+=$'\n%n@%m:%/\nyes, zoey? : '
}

3
30.08.2017, 11:56
5 ответов

Вы можете использовать этот простой sed.

sed 's/\w*_\s*//;/^$/d' infile.txt 

/^$/dудалит пустые строки, в которых строка включает только одно поле, заканчивающееся подчеркиванием foo_или _.

Результат:

357M
154=
419X    34=
3
27.01.2020, 21:09

Рассмотрим:

sed 's/[^\t]*_//; s/\t[^\t]*_/\t/g' < input

Это выполняет две (условные) замены:

  • первый говорит " любые (ноль или более) символы без табуляции, за которыми следует символ подчеркивания», замените на «(ничего)»
  • , второй говорит: «замените табуляцию, за которой следуют любые (ноль или более) символы без табуляции, за которыми следует подчеркивание» с помощью «tab» и делайте это столько раз, сколько вы найдете этот шаблон поиска.

Первый поиск необходим для того, чтобы найти начальные поля, которые следует удалить; второй подметает остальных.

Это оставляет исходные поля в своих столбцах:

357M
        154=
        419X            34=

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

sed 's/[^\t]*_\t//; s/\t[^\t]*_//g' < input

Результат:

357M
154=
419X    34=
4
27.01.2020, 21:09

Всегда есть подход "грубая сила и невежество".

  • Удаление неверных полей
  • Преобразование нескольких вкладок в одну
  • Удаление одной вкладки в начале строки
  • Удаление одной вкладки в конце строки

Это не умно, это не умно, но это работает.

В дальнейшем TAB означает буквальный символ TAB

sed -e 's/[0-9]*_//g' -e 's/TABTAB/TAB/g' -e 's/^TAB//' -e 's/TAB$//'

например,

$ cat x
357M    2054_
357_    154=    1900_
511_    419X    1481_   34=
$ sed -e 's/[0-9]*_//g' -e 's/            /       /g' -e 's/^     //' -e 's/     $//' < x
357M
154=
419X    34=
2
27.01.2020, 21:09

awk:

awk 'a=""; {for(i=1; i<=NF; ++i) {if($i ~ /[MX=]$/) a=(a?a"\t":"")$i}; \
     if(a) print a}' file.txt
  • a=""устанавливает переменную aв нулевое значение для текущей записи, т. е. делает aспецифичной для записи

  • for(i=1; i<=NF; ++i) {if($i ~ /[MX=]$/) a=(a?a"\t":"")$i}перебирает поля, проверяет, заканчивается ли поле на M, Xили =, если да, добавляет поле к переменной aс вкладкой для разделения между ранее сохраненным полем

  • if(a) print aпечатает a, если оно не равно нулю


Игра в гольф:

awk 'a="";{for(i=1;i<=NF;++i)if($i~/[MX=]$/)a=(a?a"\t":"")$i;if(a)print a}'

Пример:

% cat file.txt                                                                    
357M        2054_
357_        154=        1900_
511_        419X        1481_        34=

% awk 'a=""; {for(i=1; i<=NF; ++i) {if($i ~ /[MX=]$/) a=(a?a"\t":"")$i};  if(a) print a}' file.txt
357M
154=
419X    34=
2
27.01.2020, 21:09

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

sed -e 's/$/\t/' -e 's/[^\t]*_[^\t]*\t//g' -e 's/\t$//'

Это

  1. Добавляет табуляцию в конце каждой строки (таким образом создавая, по сути, n+1  -е поле, которое является нулевым ).
  2. Находит все поля (строки не -символов табуляции ), которые содержат _и удаляет их и следующую вкладку, ничем их не заменяя. Это работает с n  -м полем (, т. е. с последним полем в исходной строке ). потому что шаг 1 добавил вкладку в конце.
  3. Удаляет лишнюю вкладку в конце строки.

Здесь есть функция (, о которой, как я знаю, вы не просили, но вы оцените ее, когда увидите, что она доступна )что он сохраняет пустые поля:

$ cat file3
The             brown           jumps           the             dog.
        quick           fox             over            lazy
Four            and_            years
        score           seven           ago...

$ (the_above_command) file3
The             brown           jumps           the             dog.
        quick           fox             over            lazy
Four                    years
        score           seven           ago...

П.С. В зависимости от того, какая у вас версия sed, вам может потребоваться ввести в команду фактические вкладки вместо \t. Или, если вы используете bash, вы можете использовать $'…'для командных строк sed, содержащих \t.

1
27.01.2020, 21:09

Теги

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