Как заменить совпадающую строку, если строка n+2 содержит определенную строку

={1}.*es lo mismo que =.*y coincidirá con un signo igual, seguido de cualquier cantidad de caracteres. Las expresiones regulares suelen ser "codiciosos", por lo que intentan encontrar la coincidencia más larga. El uso de ese patrón contra una cadena de signos iguales coincidirá con toda la cadena, ya que no hay forma de que el motor de expresiones regulares sepa que se refiere a caracteres que no sean signos iguales.

Utilice =[^=]*para hacer coincidir un signo igual seguido de cualquier cantidad de caracteres que no sean signos iguales. O =[^=].*para coincidir con un signo igual, seguido de cualquier otro carácter, seguido de cualquier cosa.

O, para unir líneas con asignaciones de variables más de cerca, algo como

sed -Ee 's/^([a-zA-Z0-9_]+=).*/\1/'

verificaría que la línea se vea como una asignación de variable, y luego eliminaría cualquier cosa después de =. Eso supone que los nombres de las variables solo pueden contener letras, números y guiones bajos en inglés. Es posible que deba ajustar eso.

0
21.06.2019, 19:26
5 ответов

При использовании исходного xmlпримера (сначала необходимо исправить теги, так как dependenciesне был закрыт )и с использованиемxmlstarlet

xmlstarlet ed -N "x=http://maven.apache.org/POM/4.0.0" -u "//x:dependency[x:version[contains(text(), 'com.icc.version')]]/x:groupId" -v "BANANA" data.xml

Редактировать

Если принять во внимание двойное ограничение, что изменения вносятся в groupIdтолько там, где versionсодержит com.icc.version, а groupIdне является com.icc.id, тогда следующее должно выбирать и заменять только эти узлы

xmlstarlet ed -N "x=http://maven.apache.org/POM/4.0.0" -u "//x:dependency[x:version[contains(text(), 'com.icc.version')]]/x:groupId[not(contains(text(), 'com.icc.id'))]" -v 'BANANA' data.xml

или если весь текст узла groupIDравен com.icc.id, то

xmlstarlet ed -N "x=http://maven.apache.org/POM/4.0.0" -u "//x:dependency[x:version[contains(text(), 'com.icc.version')]]/x:groupId[text() !='com.icc.id']" -v 'BANANA' data.xml

Цикл globstarот @terdon найдет файлы, и вывод будет отправлен на stdout, чтобы вы могли его проверить. Чтобы сделать изменения в файлах .pomпостоянными, включите в команду опцию -L.

xmlstarlet ed -L -N  etc.....

Вход

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <dependencies>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
        </dependency>
        <dependency>
            <groupId>com.icc.id</groupId>
            <artifactId>solution-commons</artifactId>
            <version>${com.icc.id.version}</version>
        </dependency>
        <dependency>
            <groupId>com.icc.banana</groupId>
            <artifactId>application-common</artifactId>
            <version>${com.icc.version}</version>
        </dependency>
        <dependency>
            <groupId>com.icc.id</groupId>
            <artifactId>application-common</artifactId>
            <version>${com.icc.banana}</version>
        </dependency>
    </dependencies>
</project>

Выход

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <dependencies>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
    </dependency>
    <dependency>
      <groupId>com.icc.id</groupId>
      <artifactId>solution-commons</artifactId>
      <version>${com.icc.id.version}</version>
    </dependency>
    <dependency>
      <groupId>BANANA</groupId>
      <artifactId>application-common</artifactId>
      <version>${com.icc.version}</version>
    </dependency>
    <dependency>
      <groupId>com.icc.id</groupId>
      <artifactId>application-common</artifactId>
      <version>${com.icc.banana}</version>
    </dependency>
  </dependencies>
</project>

Одно предупреждение по этому поводу. xmlstarletзависит от знания namespace, поэтому, если namespaceодинаков во всех файлах, тогда нет проблем. Если он отличается, вам нужно будет опросить каждый файл, определить namespaceи передать его как переменную.

ns=$(grep -Po "(?<=xmlns=\")[^\"]*" data.xml)
0
28.01.2020, 02:14

Сed:

printf 'g/com\.icc\.id\.version/-2 s/com\.icc\.id/abc/\n,wq\n' | ed -s file.pom
1
28.01.2020, 02:14

Сохранить строки n и n+1 в состоянии ожидания, когда есть совпадение на n -й. Прочтите n+2-й и проверьте его на заданное содержание. После матча вспомните удержание и выполните замену на abc.

 $ sed -ne '
     />com\.icc\.id</!bp
     N;h;n
     /\<com\.icc\.id\.version\>/{
         x;s/>com\.icc\.id<\(.*\n\)/>abc<\1/;x
    }
     x;G;:p;p
 ' inp.pom
2
28.01.2020, 02:14

Это больше, чем вам нужно, но это позволяет вам делать гораздо больше с вашими записями в будущем:

$ cat tst.awk
BEGIN { numLines = 3 }
{
    lineNr = (NR - 1) % numLines + 1
    rec[lineNr] = $0
}
lineNr == numLines {
    if ( rec[3] ~ /com\.icc\.id\.version/ ) {
        sub(/com\.icc\.id/,"abc",rec[1])
    }
    for (lineNr=1; lineNr<=numLines; lineNr++) {
        print rec[lineNr]
    }
    delete rec
}

$ awk -f tst.awk file
(groupId)com.icc.id(/groupId)
(artifactId)abc(/artifactId)
(version)${project.version}(/version)
(groupId)abc(/groupId)
(artifactId)ifd(/artifactId)
(version)${com.icc.id.version}(/version)

Чтобы сделать это со всеми файлами ".pom" во всех подкаталогах -, предполагая, что "файлы pom" имеют такое расширение и используя GNU awk для-i inplace:

find. -name '*.pom' -exec awk -i inplace -f tst.awk {} +
3
28.01.2020, 02:14

Если ваш файл достаточно мал и не помещается в памяти, вы можете:

$ awk '{lines[NR]=$0}END{for(i in lines){ if(lines[i] ~ /com\.icc\.id/ && lines[i+2] ~ /com\.icc\.id\.version/){gsub("com\\.icc\\.id","abc",lines[i])} print lines[i]}}' file 
(groupId)com.icc.id(/groupId)
(artifactId)abc(/artifactId)
(version)${project.version}(/version)
(groupId)abc(/groupId)
(artifactId)ifd(/artifactId)
(version)${com.icc.id.version}(/version) 

Или, немного читабельнее:

$ awk '{
        lines[NR]=$0
       }
       END{
            for(i in lines){ 
                if(lines[i] ~ /com\.icc\.id/ && 
                   lines[i+2] ~ /com\.icc\.id\.version/){
                        gsub(/com\.icc\.id/,"abc",lines[i])
                } 
            print lines[i]
            }
       }' file 
(groupId)com.icc.id(/groupId)
(artifactId)abc(/artifactId)
(version)${project.version}(/version)
(groupId)abc(/groupId)
(artifactId)ifd(/artifactId)
(version)${com.icc.id.version}(/version) 

Чтобы применить это ко всем файлам с расширением .pom(, я предполагаю, что это то, что вы подразумеваете под «файлами pom» )в каталоге commonи любых подкаталогах, вы можете сделать это (, предполагая, что вы используете bashи ГНУ gawk):

.
shopt -s globstar
tmpFile=$(mktemp)
for file in common/**/*.pom; do
    awk '{
    lines[NR]=$0
   }
   END{
        for(i in lines){ 
            if(lines[i] ~ /com\.icc\.id/ && 
               lines[i+2] ~ /com\.icc\.id\.version/){
                    gsub(/com\.icc\.id/,"abc",lines[i])
            } 
        print lines[i]
        }
   }' "$file" > "$tmpFile" && mv "$tmpFile" "$file"
   done
1
28.01.2020, 02:14

Теги

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