заменить файл внутри тегов html с помощью bash

В Linux вы можете использовать fallocate () , чтобы освободить данные в начале файла.

Освобождение файлового пространства

Установка флага FALLOC_FL_PUNCH_HOLE (доступного с Linux 2.6.38) в режиме освобождает пространство (т. Е. Создает дыру) в диапазоне байтов, начиная со смещения и продолжаясь для len байтов. В пределах указанного диапазона частичные блоки файловой системы обнуляются, а целые блоки файловой системы удаляются из файла. После успешного вызова последующие чтения из этого диапазона вернут нули.

...

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

Примерно так:

size_t maxSize = 512UL * 1024UL * 1024UL;
char buffer[ 8 * 1024 ];
struct stat sb;
int in = open( inputFile, O_RDONLY );
int out = open( outputFile, O_WRONLY | O_CREAT | O_APPEND, 0644 );
fstat( out, &sb );
size_t fileSize = sb.st_size;

for ( ;; )
{
    ssize_t bytesRead = read( in, buffer, sizeof( buffer ) );
    if ( bytesRead < 0 )
    {
        break;
    }

    ssize_t bytesWritten = write( out, buffer, bytesRead );
    if ( bytesWritten < 0 )
    {
        break;
    }

    fileSize += bytesWritten;

    if ( fileSize > maxSize )
    {
        fsync( out );
        off_t endOfHole = fileSize - maxSize;
        fallocate( out, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
            0UL, endOfHole );
    }
}

Это поддерживается только в XFS, BTRFS, EXT4 и tmpfs.

Он также требует гораздо большей проверки ошибок и может даже не компилироваться как есть. Это также очень неэффективно, так как при достижении максимального размера он будет вызывать fallocate () для каждого цикла read () / write () , и он будет каждый раз пробивайте "дырку" от начала файла.

Также нет смысла использовать буферизованный fread () / fwrite () для этого шаблона ввода-вывода. Просто read () / write () достаточно больших фрагментов.

0
24.12.2020, 20:58
2 ответа
$ cat f.html
<h1>head</h1>
<p>hello</p>
<p>world</p>
$ grep -o '<p>.*</p>' f.html | tr '[:lower:]' '[:upper:]' | sed 's/P>/p>/g'  
<p>HELLO</p>
<p>WORLD</p>


# capture other tags: grep multi-pattern e.g 'patt1\|patt2\|pattN'
$ grep -o '<p>.*</p>\|<h1>.*</h1>' f.html | tr '[:lower:]' '[:upper:]' | sed 's/P>/p>/g;s/H1>/h1>/g'
<h1>HEAD</h1>
<p>HELLO</p>
<p>WORLD</p>

# add line after h1 tag : grep+tr+sed
function foo () {
    grep -o '<p>.*</p>\|<h1>.*</h1>' "${1}" | tr '[:lower:]' '[:upper:]' | sed 's/P>/p>/g;s/H1>/h1>/g' | while read line; do 
        case "${line}" in
            "<h1>"*)
                echo "${line}"
                echo "anything that should appear after h1 tags"
            ;;
            "<p>"*)
                echo "${line}"
            ;;
        esac
    done
}

$ foo f.html
<h1>HEAD</h1>
anything that should appear after h1 tags
<p>HELLO</p>
<p>WORLD</p>

# add line after h1 tag : few [shell parameter expansion] tips + while & case statments 
function foo () {
    grep -o '<p>.*</p>\|<h1>.*</h1>' "${1}" | while read line; do 
        case "${line}" in
            "<h1>"*)
                line="${line^^}"; #capitalize (shell parameter expansion)
                echo "${line//H1>/h1>}" # find replace (shell parameter expansion)
                echo "anything that should appear after h1 tags"
            ;;
            "<p>"* | "<P>"*) # if html files contain capitalized P tag and you wanna capture them 
                line="${line^^}"; #capitalize
                echo "${line//P>/p>}" # find replace
            ;;
            "<foo>"*)
                line="${line^^}"; #capitalize 
                linopenintag="${line//<foo>/}"; # <foo>hello world</foo> ==> hello world</foo>
                innerHTML="${linopenintag//<\/foo>/}"; # hello world</foo> ==> hello world
                innerHTMLarr=(${innerHTML});  # in case i want to put each word in a spin or/and style that word differently 

                for eachword in ${innerHTMLarr[@]}; do
                    if [[ "${eachword}" == "something" ]]; then # capture special words... 
                        echo "<bar style='...'> ${eachword} </bar>"
                    else
                        echo "<bar> ${eachword} </bar>"
                    fi
                done

            ;;
        esac
    done
}
$ foo f.html 
<h1>HEAD</h1>
anything that should appear after h1 tags
<p>HELLO</p>
<p>WORLD</p>
0
28.04.2021, 23:47

xmllint+sedраствор:

xmllint --html --xpath "//p" input.html | sed 's/>[^<>]*</\U&/'

Выход:

<p>HELLO</p>
1
28.04.2021, 23:47

Теги

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