Использование sed для замены определенного шаблона

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

.
#!/bin/bash

# clear placeholder
printf "Files with no diff:\n" > placeholder

# set up sample data
echo "one" > file.00.txt
echo "one" > file.01.txt
echo "foo" > file.02.txt
echo "bar" > file.03.txt
echo "two" > file.04.txt
echo "two" > file.05.txt 

# generate array
i=0
while [ $i -lt 6 ]; do    
    array+=( file.`printf %02d $i`.txt )
    ((i++))
done

i=0
while [ $i -lt 5 ]; do
    diff --brief ${array[i]} ${array[i+1]} && \
    echo "${array[i]} ${array[i+1]}" >> placeholder 
    ((i++))
done

Результаты:

$ sh./test.sh 
Files file.01.txt and file.02.txt differ
Files file.02.txt and file.03.txt differ
Files file.03.txt and file.04.txt differ
$ cat placeholder 
Files with no diff:
file.00.txt file.01.txt
file.04.txt file.05.txt

Вам не нужно генерировать образцы данных, если у вас уже есть данные.

Объяснение кода:

Построение массива в цикле (в Bash )может быть выполнено путем итерации, как вы, очевидно, уже знаете, но нотация array+=добавляет элемент.

Очевидно, ((++))увеличивает ваш счетчик.

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

Используя нотацию&&(И ), этот код повторяет имена сравниваемых файлов в вашем файле placeholderтогда и только тогда, когда команда diffне генерирует выходных данных.

Если есть разница между файлами , diffвыводит различия на терминал. Это приводит к сбою&&(И ), поэтому в файл-заполнитель ничего не выводится.

Если у вас есть дополнительные вопросы по синтаксису, не стесняйтесь спрашивать.

4
29.06.2020, 14:58
2 ответа

На любом устройстве, совместимом с POSIX awk, вы можете использовать функцию tolower()

awk -v FS='=' 'BEGIN { OFS = FS } { $2 = tolower($2) }1 ' file

Используйте функцию mktemp()для создания временного файла для перенаправления вывода вышеприведенной команды, а затем повторно -перенаправления обратно для сохранения в -месте. Или используйте GNU awk>= 4.1 с-i inplace

Другой вариант версии, совместимой с POSIX, с использованием функции match()будет выполнять

awk 'match($0, /=([^,]*),/) { str = substr($0, RSTART+1, RLENGTH-2); sub(str, tolower(str)) }1'
4
18.03.2021, 23:23

Это возможно с GNU sed. Выберите одну из этих двух форм, исходя из жадности замены.

sed 's|=.*,|\L&|' file
sed 's|=[^,]*,|\L&|' file

Как указано в руководстве , «\Lпереводит замену в нижний регистр до тех пор, пока не будет найдено \Uили \E». &— это текст, соответствующий регулярному выражению.


Я изменил образец файла, чтобы показать, что вы должны разумно выбирать между жадными =.*,и не -жадными =[^,]*,регулярными выражениями:

$ cat file
SOMENAME=WOODSTOCK,
SOMEOTHERNAME2=JIMMY,WOODSTOCK,FINISH
$ sed 's|=.*,|\L&|' file
SOMENAME=woodstock,
SOMEOTHERNAME2=jimmy,woodstock,FINISH
$ sed 's|=[^,]*,|\L&|' file
SOMENAME=woodstock,
SOMEOTHERNAME2=jimmy,WOODSTOCK,FINISH
5
18.03.2021, 23:23

Теги

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