Команда sed - Заменить строку в файле

Я думаю, ваша основная проблема в том, что вы пытались использовать синтаксис bash в сценарии sh. Bash определяет расширения для общего знаменателя sh; если вы хотите использовать специфические для bash функции, ваш сценарий должен начинаться с #!/bin/bash, а не с #!/bin/sh. В

Sh нет синтаксиса ((...)) для арифметических выражений. Но он здесь и не нужен, вы можете использовать переносимый [ ... ] условный синтаксис. В условном [ ... ] оператор "меньше чем" записывается -lt.

Скобки {1..2} - еще одна особенность bash, которой нет в sh. Еще одна ошибка в вашем скрипте - X=$A+1, который устанавливает X в строку вида 42+1, если значение A равно 42; чтобы выполнить арифметическое вычисление, нужно использовать синтаксис арифметического выражения $((...)).

Также, в качестве общего замечания, всегда используйте двойные кавычки вокруг подстановок переменных.

Еще одна проблема с вашим кодом заключается в том, что он выглядит так, будто A - десятичное число. Арифметика Shell работает только с целыми числами. Я адаптировал алгоритм, но проверьте, что он делает, возможно, я округлил не так, как вы задумали. Использовать awk только для подсчета количества строк - излишество, wc -l - более понятный и быстрый способ сделать это. Аналогично, чтобы вывести первые N строк файла, просто вызовите head.

Еще одна ошибка заключается в том, что $i_chunk - это значение переменной i_chunk. Чтобы взять значение i и добавить _chunk, нужно разделить имя переменной скобками: ${i}_chunk.

Я понятия не имею, что должен делать цикл на j, я оставил его в покое.

#!/bin/sh
for i in 1 2
do
  input="../ExpressionSet_${i}_chunk.txt"
  for j in 1 2
  do
    A=$(wc -l <"$input")
    Y=100
    X=0
    if [ "$A" -lt "$Y" ]; then
      X=$((A+100))
    else
      X=$A
    fi
    head -n "$((X/100))" "$input" > "$i"_top1pc.txt
    head -n "$((X/20))" "$input" > "$i"_top5pc.txt
  done
done

Если вы решите написать сценарий на bash, вы можете использовать несколько возможностей bash:

  • ((...)) для арифметических оценок (но все еще только целочисленных)
  • typeset -i для объявления целочисленной переменной, так что присвоение арифметического выражения оценивает ее
#!/bin/bash
for i in 1 2
do
  input="../ExpressionSet_${i}_chunk.txt"
  for j in 1 2
  do
    A=$(wc -l <"$input")
    Y=100
    typeset -i X
    if ((A < Y)); then
      X=A+100
    else
      X=$A
    fi
    head -n "$((X/100))" "$input" > "$i"_top1pc.txt
    head -n "$((X/20))" "$input" > "$i"_top5pc.txt
  done
done

3
20.05.2017, 17:04
4 ответа

С sed :

 sed -E  's/(jvmRoute=)([a-zA-Z0-9"-])+/\1"VALUE10"/g'

Поскольку вы не указали, каким может быть исходное значение jvmRoute, я написал регулярное выражение для приведенного выше примера, но вы можете настроить его для своего потребности.
Чтобы заменить непосредственно в файле, используйте:

sed -i -E  's/(jvmRoute=)([a-zA-Z0-9"-])+/\1"VALUE10"/g' server.xml

Но использование синтаксического анализатора xml было бы лучшим способом, вероятно.

1
27.01.2020, 21:18

У вас нет строк, начинающихся с "jvmRoute". (^ означает начало строки, просто опустив это, вы должны изменить два вхождения в вашем файле.)

0
27.01.2020, 21:18
sed 's/patternFrom/patternTo/' file.txt

• "s/" означает замену того, что следует далее: эту замену теперь нужно применить к нашему файлу, путем ввод однострочной команды:

• Команды могут применяться с помощью sed только к выбранному набору строк. Эти линии идентифицируются по их порядковому номеру внутри файла, начиная со строки 1.

Например:

sed '2s/patternFrom/patternTo' file.txt

• выполняет подстановку только во второй строке

или

sed '2,$s/patternFrom/patternTo' file.txt

• выполняет подстановку со 2 строки до последней, обозначенной специальным символом «$».

Даже больше

• sed содержит внутренний буфер, называемый пространством хранения. Этот буфер можно активировать определенными командами, например 'g'. Команда 'g' приводит к замене пробела текущую строку ввода, чтобы совпадения можно было повторить в строке ввода

В вашем случае попробуйте сопоставить все вхождения во всех строках с помощью:

sed 's/patternFrom/patternTo/g' file.txt

Я думаю, что не работает шаблон

Убедитесь, что регулярное выражение работает, попробуйте с

sed 's/jvmRoute="[a-zA-Z0-9-\.]*["]/jvmRoute="VALUE10"/g
1
27.01.2020, 21:18

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

Синтаксический анализ XML должен выполняться с помощью анализатора XML.

XMLStarlet — хорошая команда, -синтаксический анализатор строк:

$ xml ed -u '//Engine/@jvmRoute' -v 'VALUE10' server.xml >server-new.xml

Это изменит значение атрибута jvmRouteвсех узлов Engineна строку VALUE10и сохранит полученный XML в server-new.xml.

Чтобы изменить значение только для узла Engine, который имеетdefaultHost="localhost":

xml ed -u '//Engine[@defaultHost="localhost"]/@jvmRoute' -v 'VALUE10' server.xml >server-new.xml

XMLStarlet доступен по адресу http://xmlstar.sourceforge.net/, но сначала проверьте свой менеджер пакетов. Иногда исполняемый файл XMLStarlet называется xmlstarlet, а не xml.

2
27.01.2020, 21:18

Теги

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