Строка замены с последовательным индексом

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

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

Кроме того, только один набор полномочий когда-либо используется за один раз — если Вы - владелец, только на полномочия владельца смотрят, и полномочия группы не имеют значения. Если Вы не владелец, но находитесь в группе, полномочия группы используются. Наконец, если Вы не находитесь в группе, ни владельце, "другие" полномочия используются. Если Вы - и владелец файла и в группе файла, биты группы не имеют значения.

9
08.03.2014, 23:14
3 ответа

enter image description here

или с GNU [119783]awk[119784]:

tail -f logfile |grep -m 1 "Server Started" | xargs echo "" >> /dev/null ;

Чтобы редактировать файлы на месте, добавьте опцию [119785]-i[119786] к [119787]perl[119788]:

Или рекурсивно:

Объяснения

-p[119790] необходимо обработать входную строку за строкой, оценить выражение, переданное в [119791]-e[119792] для каждой строки и вывести его на печать. Для каждой строки подставляем (используя оператор [119793]s/re/repl/flags[119794]) [119795]instant[119796] для себя ([119797]$&[119798]) и инкрементированное значение переменной [119799]++$n[119800]. Флаг [119801]g[119802] делает замену глобально (не один раз), а [119803]e[119804] так, чтобы замена интерпретировалась как код perl к [119805]e̲[119806] значению (не фиксированная строка).

Для редактирования на месте, где один вызов perl обрабатывает более одного файла, мы хотим, чтобы [119807]$n[119808] сбрасывалось в каждом файле. Вместо этого мы используем [119809]$n{$ARGV}[119810] (где [119811]$ARGV[119812] - обрабатываемый в настоящее время файл).

  1. [119813]awk[119814] заслуживает небольшого объяснения.
  2. Мы используем способность GNU [119815]awk[119816] разделять записи на произвольные строки (даже regexps). С помощью [119817]-vRS=instant[119818] мы устанавливаем [119819]r̲ecord s̲eparator[119820] на [119821]instant[119822]. [119823]RT[119824] является переменной, которая содержит то, что было согласовано с [119825]RS[119826], поэтому обычно [119827]instant[119828], за исключением последней записи, где это будет пустая строка. Во входных данных выше записи ([119829]$0[119830]) и терминаторы записи ([119831]RT[119832]) равны ([119833][$0|RT][119834]):
  3. Так что все, что нам нужно сделать, это вставить в начало каждой записи, кроме первой, инкрементирующее число.
  4. Это то, что мы делаем выше. Для первой записи [119835]n[119836] будет пустой. Мы устанавливаем ORS (the [119837]o̲utput r̲ecord s̲eparator[119838]) на RT, так что [119839]awk[119840] распечатает [119841]n $0 RT[119842]. Он делает это по второму выражению ([119843]++n[119844]), которое всегда оценивается до true (ненулевое число), и поэтому для каждой записи выполняется действие по умолчанию (распечатка [119845]$0 ORS[119846]).[119330].
13
27.01.2020, 20:05

sed действительно не лучший инструмент для работы, вам нужно что-то с лучшими возможностями написания сценариев. Вот несколько вариантов:

  • perl

     perl -000pe 's / Instant / $ &. $. / e 'file 
     

    -p означает «печатать каждую строку» после применения любого сценария, заданного с помощью -e . -000 включает «режим абзаца», поэтому записи (строки) определяются последовательными символами новой строки ( \ n ), это позволяет правильно обрабатывать строки с двойным интервалом. $ & - последний найденный шаблон, а $. - номер текущей строки входного файла. e в s /// e позволяет мне оценивать выражения в операторе подстановки.

  • awk (предполагается, что ваши данные в точности такие, как показано, с тремя полями, разделенными пробелами)

     awk '{if (/./) print $ 1, $ 2 ++ k, $ 3; else print} 'file 
     

    Здесь мы увеличиваем переменную k k , только если текущая строка не пуста /./ в этом случае мы также печатаем необходимую информацию. Пустые строки печатаются как есть.

  • различные оболочки

      n = 0; пока читаем -r a b c; сделать 
    если ["$ a"]; затем 
     ((n ++)) 
    printf "% s% s% s% s \ n" "$ a" "$ b" "$ n" "$ c" 
    else 
    printf "% s% s% s \ n" "$ a" "$ b" "$ c" 
    fi 
    done 

    Здесь каждая строка ввода автоматически разделяется на пробелы, а поля сохраняются как $ a , $ b и $ c . Затем внутри цикла $ c увеличивается на единицу для каждой строки, для которой $ a не является пустым, и его текущее значение печатается рядом со вторым полем, $ b .

ПРИМЕЧАНИЕ: все вышеперечисленные решения предполагают, что все строки в файле имеют один и тот же формат. Если нет, ответ @Stephane - это то, что вам нужно.


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

for file in ./*; do perl -i -000pe 's/instant/$& . $./e' "$file"; done

ВНИМАНИЕ: это предполагает простые имена файлов без пробелов, если вам нужно разобраться с чем-то более сложным, используйте (при условии ksh93 , zsh или bash ):

find . -type f -print0 | while IFS= read -r -d ''; do
    perl -i -000pe 's/instant/$& . $./e' "$file"
done
4
27.01.2020, 20:05

Если вы хотите решить эту проблему с помощью sed, вы можете использовать что-то вроде этого (вbash):

i=0
while read -r line; do
  sed "s/\(instant\)/\1${i}/" <<< "${line}"
  [[ ${line} =~ instant ]] && i=$(( i + 1 ))
done < file

или более переносимым решением будет:

i=0
while read -r line; do
  echo "${line}" | sed "s/\(instant\)/\1${i}/"
  if echo "${line}" | grep -q inst; then
    i=$(( i + 1 ))
  fi
done < file
0
30.04.2020, 11:34

Теги

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