Почему sed дублирует первую добавленную строку (отправляя вывод sed в тот же файл)? - PullRequest
0 голосов
/ 28 февраля 2020

Начальный файл (/etc/crontabs/root):

# do daily/weekly/monthly maintenance
# min   hour    day     month   weekday command
*/15    *       *       *       *       run-parts /etc/periodic/15min  
0       *       *       *       *       run-parts /etc/periodic/hourly 
0       2       *       *       *       run-parts /etc/periodic/daily  
0       3       *       *       6       run-parts /etc/periodic/weekly 
0       5       1       *       *       run-parts /etc/periodic/monthly

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

sed '/^#/ d; s/\/etc/\/root\/etc/' /etc/crontabs/root >> /etc/crontabs/root

... который должен удалить все комментарии, заменить /etc на /etc/root ... и добавить результат в тот же файл.

Неверный вывод (обратите внимание дополнительная строка, начинающаяся с */15):

# do daily/weekly/monthly maintenance
# min   hour    day     month   weekday command
*/15    *       *       *       *       run-parts /etc/periodic/15min
0       *       *       *       *       run-parts /etc/periodic/hourly
0       2       *       *       *       run-parts /etc/periodic/daily
0       3       *       *       6       run-parts /etc/periodic/weekly
0       5       1       *       *       run-parts /etc/periodic/monthly        

*/15    *       *       *       *       run-parts /root/etc/periodic/15min     
0       *       *       *       *       run-parts /root/etc/periodic/hourly    
0       2       *       *       *       run-parts /root/etc/periodic/daily     
0       3       *       *       6       run-parts /root/etc/periodic/weekly    
0       5       1       *       *       run-parts /root/etc/periodic/monthly   

*/15    *       *       *       *       run-parts /root/root/etc/periodic/15min

Ожидаемый / требуемый результат :

# do daily/weekly/monthly maintenance
# min   hour    day     month   weekday command
*/15    *       *       *       *       run-parts /etc/periodic/15min
0       *       *       *       *       run-parts /etc/periodic/hourly
0       2       *       *       *       run-parts /etc/periodic/daily
0       3       *       *       6       run-parts /etc/periodic/weekly
0       5       1       *       *       run-parts /etc/periodic/monthly        

*/15    *       *       *       *       run-parts /root/etc/periodic/15min     
0       *       *       *       *       run-parts /root/etc/periodic/hourly    
0       2       *       *       *       run-parts /root/etc/periodic/daily     
0       3       *       *       6       run-parts /root/etc/periodic/weekly    
0       5       1       *       *       run-parts /root/etc/periodic/monthly   

Идеи?

Ответы [ 2 ]

2 голосов
/ 28 февраля 2020

Вы не должны записывать в тот же файл, из которого читаете. Он прочитает строки, которые вы добавили в файл, и продолжит их обработку. Поэтому, когда он достигает строк с /root/etc, он заменит /etc в этом, производя /root/root/etc. Он может застрять в бесконечном l oop, поскольку он продолжает расширять файл и никогда не достигнет конца.

Что вы можете сделать, это скопировать файл crontab в новый файл, а затем использовать sed добавить к этому.

cp /etc/crontabs/root /tmp/new_crontab
sed '/^#/ d; s/\/etc/\/root\/etc/' /etc/crontabs/root >> /tmp/new_crontab
cp /tmp/new_crontab /etc/crontabs/root
1 голос
/ 29 февраля 2020

Если вам нужен один вкладыш, он довольно прост, используя ed:

printf "%s\n" ka '1,$t' "'a,\$g/^#/d" "'a+1,\$s/\/etc/\/root\/etc/" w | ed -s /etc/crontabs/root

или немного легче читать с помощью heredo c:

ed -s /etc/crontabs/root <<'EOF'
ka
1,$t
'a,$g/^#/d
'a+1,$s/\/etc/\/root\/etc/
w
EOF
...