Заменить только первый символ

Как определили другие, проблема с вашей командой заключается в том, что она включает каталоги, а tar архивирует их рекурсивно. Если каталог был недавно изменен, все файлы в нем и его подкаталогах будут включены, независимо от того, были они изменены или нет.

Если вы не хотите создавать резервные копии метаданных каталога, просто скажите find не печатать имена каталогов. Недостаточно пропустить корень: то же самое может случиться и с подкаталогами.

find "$SOURCEDIR" -mtime -1 ! -type d -print | xargs -r tar -rcf "$ARCHIVE"

Использование xargs не работает с именами файлов, содержащими пробелы и некоторые другие специальные символы . Это легко исправить: используйте -exec вместо xargs .

find "$SOURCEDIR" -mtime -1 ! -type d -exec tar -rcf "$ARCHIVE" {} +

Если вы хотите создать резервную копию метаданных каталога, позвольте find распечатать все и вместо этого указать tar не рекурсивно переходить в подкаталоги. Поскольку find выполняет рекурсию, tar в этом не нуждается.

find "$SOURCEDIR" -mtime -1 -exec tar -rcf "$ARCHIVE" --no-recursion {} +

При таком подходе вы можете избежать использования tar -rc и вместо этого решить проблему повторяющихся вызовов tar, сначала создавая архив только с корневым каталогом, а затем добавляя его в пакетах. (Почему корневой каталог? Потому что GNU tar боится создать пустой архив.)

tar -cf "$ARCHIVE" --no-recursion "$SOURCEDIR"
find "$SOURCEDIR" -mindepth 1 -mtime -1 -exec tar -rf "$ARCHIVE" --no-recursion {} +

3
26.07.2016, 00:00
2 ответа

Чистое bash решение

while IFS=\, read -r a b ; do echo "$a;$b" ; done <file.csv

Или просто для развлечения

paste -d\; <(cut -d, -f1 file.csv) <(cut -d, -f1 --complement file.csv)
3
27.01.2020, 21:07

g в:

sed 's/,/;/g'

предназначен для глобально , то есть заменяет все вхождения ], с ; .

Если вы хотите делать только одну замену в строке, удалите g :

sed 's/,/;/'

И для полноты:

Вы также можете указать, какое вхождение нужно заменить. Например, чтобы заменить только второе вхождение:

sed 's/,/;/2'

С помощью GNU sed вы также можете заменить все вхождения, начиная со второго (фактически, все, кроме первого) на:

sed 's/,/;/2g'

To в этом случае выполните две замены:

sed 's/,/;/;s/,/;/'

Сложнее становится, когда шаблон может соответствовать замене (или ее частям), например, при замене , на <,> . sed не имеет встроенного механизма для решения этой проблемы. В этом случае вы можете использовать perl вместо этого:

perl -pe '$i = 0; s/,/$i++ < 2 ? "<,>" : $&/ge'

perl -pe - это perl режим sed (обратите внимание, что синтаксис регулярного выражения отличается). С флагом e оператора s /// замена рассматривается как код. Здесь мы заменяем , на <,> только тогда, когда наш увеличиваемый счетчик <2.В противном случае мы заменяем , самим собой ( $ & фактически ссылается на совпавшую строку, например & в sed s команда).

Вы можете обобщить это для диапазона или набора замен. Как для 3 -го 5 -го и 7 -го до 9 -го :

perl -pe '$i = 0; s/,/$i++;
   $i >=3 && $i <= 5 || $i >= 7 && $i <= 9 ? "<,>" : $&/ge'

Чтобы заменить только первое вхождение во всем вводе (в отличие от в каждой строке ):

sed -e 's/,/;/;t done' -e b -e :done -e 'n;b done'

То есть при первой успешной подстановке перейти в цикл, который просто печатает остальную часть ввода.

В GNU sed вы можете использовать псевдоадрес 0 :

sed '0,/,/s//;/'

Примечание

Я полагаю, что это опечатка, но команда

sed '/s/,/;/g'

, которую вы написали в своем вопрос совсем в другом.

Это делается:

sed '/start/,/end/g'

где start - это s , а end - это ; . То есть, применяя команду g (замените пространство шаблонов содержимым удерживаемого пространства (здесь пусто, поскольку вы никогда ничего не удерживаете)) для разделов файла между разделами, содержащими s и следующий, содержащий ; .

16
27.01.2020, 21:07

Теги

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