Использование sed для добавления символа в n-ю позицию совпадающей строки

Вы можете просто сделать:

case $1 in (/*) pathchk -- "$1";; (*) ! : ;; esac

Этого должно быть достаточно. И он запишет диагностику в stderr и вернет ошибку для недоступных или несоздаваемых компонентов. pathchk не о существующих путевых именах - это о используемых путевых именах.

Утилита pathchk должна проверять, что один или несколько путей действительны (то есть, они могут использоваться для доступа или создания файла, не вызывая синтаксических ошибок) и переносимая ] (то есть без результата усечения имени файла) . Опция -p предоставляет более обширные проверки переносимости.

По умолчанию утилита pathchk проверяет каждый компонент каждого операнда pathname на основе базовой файловой системы. Диагностика должна быть написана для каждого операнда pathname , который:

  • длиннее, чем {PATH_MAX} байтов (см. Значения переменных Pathname в )

  • Содержит любой компонент, длина которого превышает {NAME_MAX} байтов в его содержащем каталоге

  • Содержит любой компонент в каталоге, который недоступен для поиска

  • Содержит любой символ в любом компоненте, который недействителен в содержащем его каталоге

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

Не считается ошибкой, если один или несколько компонентов операнда путевого имени не существуют, пока может быть создан файл, соответствующий путевому имени , указанному отсутствующими компонентами. это не нарушает ни одну из проверок, указанных выше.

5
05.02.2017, 21:12
4 ответа

Если вы хотите вставить после n -го символа (где n - произвольное значение), тогда вы следует избегать sed . Для этой работы есть инструменты получше (например awk или perl , python и т. Д.), Например. с awk вы можете использовать переменную n , чтобы вставить STRING после n -го символа в каждое поле, которое соответствует PATTERN :

awk -vn=2 'BEGIN{FS=OFS=","}{for (i=1; i<=NF; i++){ if ($i ~ /PATTERN/){
h=substr($i,1,n);t=substr($i,n+1,length($i));$i=h "STRING" t}}};1' infile

Предполагается, что ваш файл является простым файлом csv (без запятых в ваших полях).

2
27.01.2020, 20:33

Другой подход:

$ sed 's/"\([^"]*blah[^"]*"\)/"N\1/g' test.txt 
"N1blah8","na","N8blah4"  
"N2blah5","na","N10blah4"  
"N5blah5","na","1blah234

Регулярное выражение ищет ", затем 0 или более символов, отличных от " , за которыми следует бла , а затем затем 0 или более не- " снова. Из-за скобок это захвачено и позже может называться \ 1 . Таким образом, команда будет замените совпавший шаблон на себя ( \ 1 ), но с добавлением "N . Вот почему первый " находится вне скобок. Модификатор / g в конце заставляет его заменять всю совпадающую строку в каждой строке.

Если ваш sed ] поддерживает его, вы можете упростить его до:

sed -E 's/"([^"]*blah[^"]*")/"N\1/g'
7
27.01.2020, 20:33

Разбор и обработка CSV может быть действительно сложной задачей. Вот perl oneliner, который ставит N перед первой и третьей колонкой, независимо от содержимого:

Шаг 1, убрать двойные кавычки:

@F = map { /"(.*)"/ } @F;

Шаг 2, вставить N в первую и третью колонку

$F[0,2] =~ s/^/N/;

Шаг 3, присоединить массив как CSV

printf qq("%s"\n), join q(","), @F

запустить perl:

perl -F, -ane '@F = map { /"(.*)"/ } @F; $F[0,2] =~ s/^/N/; printf qq("%s"\n), join q(","), @F' csvfile

Edit: новый подход, чтобы избежать риска безопасности выражения eval (спасибо terdon).

1
27.01.2020, 20:33

Чтобы заставить sed повторять подстановку для всех совпадений в строке, добавьте флаг g после последнего /:

$ sed 's/[^"]*blah/N&/g' test.txt

Флаг g заставит подстановку производиться "для всех непересекающихся совпадений регулярного выражения, а не только для первого" (цитата из руководства на моей системе).

Я также немного изменил регулярное выражение, чтобы совпадали все символы, которые не являются " перед blah. Таким образом, подстановка вставит N непосредственно перед первой цифрой, сразу после ".

5
27.01.2020, 20:33

Теги

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