예를 들어 행 n+2(버전 행에 com.icc.id.version이 포함되어 있음)인 경우 com.icc.id를 "abc"로 바꿉니다. 다른 것이라면 교체하지 마십시오. 이는 "common" 폴더의 모든 하위 디렉터리에 있는 모든 pom 파일에 대해 작동합니다.
<groupId>com.icc.id</groupId>
<artifactId>abc</artifactId>
<version>${project.version}</version>
<groupId>com.icc.id</groupId>
<artifactId>ifd</artifactId>
<version>${com.icc.id.version}</version>
답변1
이는 필요한 것 이상이지만 나중에 기록으로 더 많은 작업을 수행하는 데 도움이 될 수 있습니다.
$ 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 {} +
답변2
n번째 행이 일치하면 n번째 행과 n+1번째 행을 예약 상태로 저장합니다. 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
답변3
파일이 메모리에 들어갈 만큼 작은 경우 다음을 수행할 수 있습니다.
$ 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 파일"이 의미하는 것이라고 가정합니다) 다음을 수행할 수 있습니다( , 및 GNU 를 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
답변4
원래 예제를 사용하고 (태그가 닫히지 않았 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
@terdon의 루프가 globstar
파일을 찾고 출력을 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)