Используйте sed с переменной в цикле for

echo> file был бы простым решением. Но как только вы удалили файл, это больше невозможно.

Но подождите! Поскольку вы используете файловую систему ext4, я предполагаю, что этот tar работает в Linux. (Некоторые, но не все другие варианты Unix допускают подобное решение.) В Linux вы все еще можете получить доступ к удаленному, но открытому файлу через / proc / PID / fd / FD , где PID - это идентификатор процесса, у которого открыт файл, а FD - это дескриптор файла, через который открывается файл. Этот файл представляет собой символическую ссылку на файл, но это магическая ссылка. Он остается в силе, даже если файл удален. Если вы посмотрите на него с помощью ls -l , вы увидите что-то вроде

/proc/1234/fd/4 -> /path/to/file (deleted)

, по всей видимости, неработающую ссылку, но вы действительно можете открыть этот файл. В частности, вы можете обрезать его, используя что-то вроде :> / proc / 1234 / fd / 4 .

Если вы работаете в системе без / proc , вы можете использовать отладчик, чтобы заставить сам процесс tar выполнить усечение за вас. Присоедините отладчик к процессу, затем заставьте его выполнить truncate (4) , где 4 - дескриптор файла, из которого tar читает. Например, с GDB вы можете попробовать что-то вроде

$ ps
…     find the PID of the tar process, e.g. 1234
$ lsof -p1234
…     find the file descriptor that you want to act on, e.g. 4
$ gdb -pid 1234
…
(gdb) call truncate(4)
(gdb) detach

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

1
02.05.2018, 01:55
2 ответа

Включая перенаправление в цикл, вы перезаписываете test.txtпри каждой итерации. Вместо этого вы можете использовать цикл, чтобы создать сценарий для sedи обработать файл с ним только один раз :

.
for i in "${arr[@]}" ; do
    printf 's/%s/ANON/g\n' "$i"
done | sed -r -f- /log > /test.txt

Или просто:

printf 's/%s/ANON/g\n' "${arr[@]}" | sed -r -f- /log > /test.txt

Обратите внимание, что он все еще может сломаться, если массив содержит символы со специальным значением в sed (, что может даже привести к уязвимости внедрения команд, если содержимое массива не полностью находится под вашим контролем ).

3
27.01.2020, 23:23

Я предполагаю, что вы хотите заменить все вхождения любого слова в вашем массиве arrсловом ANON.

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

Также существует потенциальная проблема, если какое-либо из слов содержит символы, которые могут быть интерпретированы как символы регулярного выражения, например *и [.

Было бы безопаснее проводить точное сравнение строк для каждой замены. Вы можете сделать это с помощьюawk:

{
    while (offset = index($0, str))
        $0 = substr($0, 1, offset - 1) "ANON" substr($0, offset + length(str))
}
{ print }

Это заменит все вхождения значения strстрокой ANON, даже если strсодержит символы регулярного выражения.

Чтение строк из файла (с дополнительным бонусом, заключающимся в том, что второй столбец файла строк с разделителями табуляции -содержит строку для замены на):

BEGIN { FS = "\t" }
NR == FNR { str[$1] = $2; next }
{
    for (s in str) {
        sl = length(s)
        while (offset = index($0, s))
            $0 = substr($0, 1, offset - 1) str[s] substr($0, offset + sl)
    }
}
{ print }

Учитывая вкладку -строки с разделителями stringsкак

*password*    *redacted*
My Name       Not really my name

... и текстовый файл file.txtкак

Password for the account belonging to My Name: *password*

... код awk выдаст

Password for the account belonging to Not really my name: *redacted*

при запуске как

awk -f script.awk strings file.txt
0
27.01.2020, 23:23

Теги

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