Замена строк, содержащих шаблон с sed

Файловые системы, где Вы не можете изменить дату символьной ссылки, распространены. Это сам по себе не ошибка bindfs или sshfs.

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

В соответствии с Linux, rsync вызовы utimensat с AT_SYMLINK_NOFOLLOW отметьте для изменения времен символьной ссылки. Насколько я могу сказать, проблема состоит в том, что API FUSE не имеет никакого соответствующего флага для utimens (или utime), таким образом, реализация файловой системы только видит запрос для изменения времени и никакого признака того, перейти ли по символьной ссылке или нет. При недостатке в любом определенном признаке и bindfs и sshfs действуют обратно совместимым способом: они изменяют цель символьной ссылки. Для разорванной символьной связи это приводит к ошибке ENOENT.

На первый взгляд я думал, что это было ошибкой в FUSE: так как FUSE не может передать AT_SYMLINK_NOFOLLOW флаг, это должно возвратить ошибку (EINVAL или ENOTSUP). Однако от поверхностного чтения кода VFS Linux, похоже, что определенный для файловой системы код вызывается или на символьную ссылку или на ее цель и никогда не должен поэтому переходить ни по какой символьной ссылке. Это имеет смысл: цель символьной ссылки может быть в другой файловой системе.

Таким образом, я думаю, что это - ошибка в bindfs и sshfs (и вероятно во многих других файловых системах FUSE): если проинструктировано для изменения метаданных символьной ссылки они должны только влиять на ту символьную ссылку или возвратить ошибку, если требуемое изменение не возможно.

3
21.07.2015, 17:33
2 ответа
sed '/^[[:alpha:]]/{$!N;s/\n/       /;}' <<\DATA
NAME_A
12,1
NAME_B
21,2
DATA

OUTPUT

NAME_A  12,1
NAME_B  21,2

Этот адрес обращается к строкам, начинающимся с буквы, включает следующую, если она есть, и заменяет символ табуляции на новую строку.

обратите внимание, что бит s / \ n / / содержит здесь буквальный символ табуляции, хотя некоторые sed могут также поддерживать \ t ] escape на своем месте

Чтобы справиться с рекурсивной ситуацией, вам нужно сделать ее немного более устойчивой, например:

sed '$!N;/^[[:alpha:]].*\n[^[:alpha:]]/s/\n/    /;P;D' <<\DATA
NAME_A
NAME_B
12,1  
NAME_C
21,2
DATA

OUTPUT

NAME_A
NAME_B  12,1
NAME_C  21,2

Это скользит по набору данных всегда на одну строку вперед. Если две строки ^ [[: alpha:]] встречаются одна за другой, это не означает ошибочную замену новой строки, как вы можете видеть.

7
27.01.2020, 21:10

Другое решение:

sed -e :a -e '$!N;s/\n\([^[:alpha:]]\)/ \1/;ta' -e 'P;D'

Добавляет текущую строку к предыдущей, если она не начинается с алфавита.

Обновлено

Решение @mikerserv после нашего обсуждения:

sed ':a
/^[[:alpha:]]/{$!N;/\n[^[:alpha:]]/!ba;s/\(.*\)\n/\1\t/}
' file

Объяснение

В строке, начинающейся с буквенного символа, он вытягивает следующий, если он есть, то, если он может адресовать новую строку, за которой следует не алфавитным символом, он выбирает все по шаблону пробел до последней строки новой строки и выполняет замену на нем - изменение последняя новая строка вкладки. Но если нет, он разветвляется и пытается снова.

2
27.01.2020, 21:10

Теги

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