Выбор строки из шаблона, замена на новую строку и инкрементный номер для каждого изменения

ls -l вернет размер файла, о котором сообщает файловая система.

wc -c попытается прочитать файл, чтобы определить «фактический» размер. По моим наблюдениям, сначала кажется, что он пытается искать до конца, и если это не сработает, он считывает весь файл, считая его размер.

Это простое описание того, что делают эти два инструмента, но оно приводит к ряду последствий для результатов:

ls выдаст неверный результат для определенных файловых систем. Например, виртуализированные файловые системы, такие как / proc , будут сообщать нулевой размер для многих файлов, потому что эти «файлы» физически нигде не хранятся; они генерируются в соответствии с требованиями программного обеспечения.

wc не будет работать вообще для файлов без разрешений на чтение, тогда как ls требует только разрешений для перечисления каталога (сравните ls -l / etc / shadow с wc -c / etc / shadow ).

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

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

1
09.07.2016, 14:33
3 ответа

Судя по вашей попытке с sed, похоже, что шаблон, который вы пытаетесь сопоставить, - "> text_ , и вы хотите добавить число и " после этого

Это возможно с awk .

awk 'BEGIN {cnt=1} /^">text_/ { gsub("_.*$","_"cnt++"\"",$0) } { print}'

например.

$ cat x
">text_lots of other bits of text"
other lines of text
">text_lots of other bits of text"
other lines of text
">text_lots of other bits of text"
other lines of text

$ awk 'BEGIN {cnt=1} /^">text_/ { gsub("_.*$","_"cnt++"\"",$0) } { print}' x
">text_1"
other lines of text
">text_2"
other lines of text
">text_3"
other lines of text

Вы можете изменить шаблон поиска ^ "text_ , чтобы идентифицировать строки, которые вы хотите изменить, и вызов gsub () выполнит замену; в этом случае с первого _ до конца строки заменяется на _ , затем счетчик, затем "

3
27.01.2020, 23:13

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

$ cat script 
#!/bin/bash
i=1
while read a ; do
    if [[ "$a" =~ "\">text_${i}".* ]]
    then echo "\">text_${i}\"" ; i=$((i+1))
    else echo "$a"
    fi
done
$ cat input 
">text_1_lots of other bits of text"
other lines of text
">text_2_lots of other bits of text"
other lines of text
">text_3_lots of other bits of text"
other lines of text
$ cat input | bash script 
">text_1"
other lines of text
">text_2"
other lines of text
">text_3"
other lines of text
2
27.01.2020, 23:13

perl может сделать это с синтаксисом, аналогичным синтаксису sed , но позволяя прямую оценку индекса замены, например

perl -pe 's/>text_.*/sprintf "text_%d", ++$n/pe' file

См. Также Замените строку последовательным индексом .

Однако, поскольку в вашем случае текст уже пронумерован, проще просто обрезать ненужную часть, захватив и заменив ее - например,

sed -E 's/(>text_[0-9]{1,}).*/\1/' file
2
27.01.2020, 23:13

Теги

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