Как применить мою команду sed к некоторым строкам всех моих файлов? - PullRequest
0 голосов
/ 30 октября 2019

У меня 95 файлов, которые выглядят следующим образом:

2019-10-29-18-00/dev/xx;512.00;0.4;/var/x/xx/xxx
2019-10-29-18-00/dev/xx;512.00;0.68;/xx
2019-10-29-18-00/dev/xx;512.00;1.84;/xx/xx/xx
2019-10-29-18-00/dev/xx;512.00;80.08;/opt/xx/x
2019-10-29-18-00/dev/xx;20480.00;83.44;/var/x/x
2019-10-29-18-00/dev/xx;3584.00;840.43;/var/xx/x
2019-10-30-00-00/dev/xx;2048.00;411.59;/
2019-10-30-00-00/dev/xx;7168.00;6168.09;/usr
2019-10-30-00-00/dev/xx;3072.00;1036.1;/var
2019-10-30-00-00/dev/xx;5120.00;348.72;/tmp
2019-10-30-00-00/dev/xx;20480.00;2033.19;/home
2019-10-30-12-00;/dev/xx;5120.00;348.72;/tmp
2019-10-30-12-00;/dev/hd1;20480.00;2037.62;/home
2019-10-30-12-00;/dev/xx;512.00;0.43;/xx
2019-10-30-12-00;/dev/xx;3584.00;794.39;/xx
2019-10-30-12-00;/dev/xx;512.00;0.4;/var/xx/xx/xx
2019-10-30-12-00;/dev/xx;512.00;0.68;/xx
2019-10-30-12-00;/dev/xx;512.00;1.84;/var/xx/xx
2019-10-30-12-00;/dev/xx;512.00;80.08;/opt/xx/x
2019-10-30-12-00;/dev/xx;20480.00;83.44;/var/xx/xx
2019-10-30-12-00;/dev/x;3584.00;840.43;/var/xx/xx

Для некоторых строк у меня есть 2019-10-29-18-00/dev, а для некоторых других строк у меня есть 2019-10-30-12-00;/dev/

Я хочудобавить ; перед /dev/ там, где его нет, поэтому для этого я использую эту команду sed:

sed 's/\/dev/\;\/dev/'

Но как я могу применить эту команду для каждой строки, где ;отсутствует ? Я пытаюсь это:

for i in $(cat /home/xxx/xxx/xxx/*.txt | grep -e "00/dev/")
do 
sed 's/\/dev/\;\/dev/' $i > $i
done

Но это не работает ... Вы можете мне помочь?

Ответы [ 5 ]

1 голос
/ 30 октября 2019

Не могли бы вы попробовать следовать с GNU awk, если вы согласны с этим.

awk -i inplace '/00\/dev\//{gsub(/00\/dev\//,"/00;/dev/")} 1'  *.txt

sed решение: Протестировано с GNU sed для нескольких файлов, и все работало нормально.

sed -i.bak  '/00\/dev/s/00\/dev/00\;\/dev/g' *.txt
0 голосов
/ 31 октября 2019

Самый простой способ - настроить регулярное выражение так, чтобы оно выглядело немного шире, чем '/ dev /', например

sed -i -E 's|([0-9])/dev|\1;/dev|'

(обратите внимание, что я пользуюсь гибким подходом sed к разделителямКроме того, -E изменяет синтаксис группы)

В качестве альтернативы, sed позволяет вам фильтровать, какие строки он обрабатывает:

sed -i '/[0-9]\/dev/ s/\/dev/;/dev/'

При этом используется то же замещение, что у вас уже есть, но применяется только кстроки, которые соответствуют регулярному выражению фильтра

0 голосов
/ 31 октября 2019

Это может сработать для вас (GNU Sed & Parallels):

parallel -q sed -i 's#;*/dev#;/dev#' ::: *.txt

или, если вы предпочитаете:

sed -i 's#;*/dev#;/dev#' *.txt
0 голосов
/ 30 октября 2019

Игнорировать строки с помощью ;/dev.

sed '/;\/dev/{p;d}; s^/dev^;/dev^'

/;\/dev/ проверяет, имеет ли строка ;/dev. Если он имеет ;/dev do: p - вывести текущую строку и d - начать с начала.

Вы можете использовать любой символ с командой s в sed. Кроме того, нет необходимости в экранировании \;, просто ;.

Как я могу применить эту команду для каждой строки, где;пропал, отсутствует ? Я пытаюсь это

Не редактировать тот же файл, перенаправляя на тот же файл $i > $i. Думаю об этом. Как вы можете переписать и прочитать из одного и того же файла одновременно? Вы не можете, полученный файл в большинстве случаев будет пустым, так как > $i сначала «выполнит», и файл будет пуст, затем sed $i запустится и прочитает пустой файл. Используйте временный файл sed ... "$i" > temp.txt; mv temp.txt "$i" или используйте расширение gnu -i sed для редактирования на месте.

Что вы действительно хотите сделать:

grep -l '00/dev/' /home/xxx/xxx/xxx/*.txt |
xargs -n1 sed -i '/;\/dev/{p;d}; s^/dev^;/dev^'

grep -l распечаткисписок файлов, которые соответствуют шаблону, затем xargs для каждого отдельного -n1 файлов выполняет sed, который -i редактирует файлы на месте.

0 голосов
/ 30 октября 2019

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

for f in $(cat /home/xxx/xxx/xxx/*.txt)
do 
    [[ -f "$f" ]] && sed -Ei '/00\/dev/ s/([^;])(\/dev)/\1;\2/' "$f"
done
...