={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.
При использовании исходного 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)
Сed
:
printf 'g/com\.icc\.id\.version/-2 s/com\.icc\.id/abc/\n,wq\n' | ed -s file.pom
Сохранить строки 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
Это больше, чем вам нужно, но это позволяет вам делать гораздо больше с вашими записями в будущем:
$ 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 {} +
Если ваш файл достаточно мал и не помещается в памяти, вы можете:
$ 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