여러 열과 구분 기호로 ","가 포함된 .csv 파일이 있습니다. URL은 첫 번째 열에 있습니다. 다른 열을 제거하지 않고 모든 URL을 도메인으로 변환해야 합니다.
내가 가지고 있는 데이터의 예:
https://www.example.com/dog/url/path/cat.php,column2,$3,4
http://www.unix.random.com/index.html,column2,$3,4
http://example.com/dog/cat.php,column2,$3,4
www.example.com/dog/,column2,$3,4
example.com/url/path/cat/dog,column2,$3,4
https://example.com/,column2,$3,4
https://www.unix.random.com,column2,$3,4
http://www.example.com,column2,$3,4
http://example.com,column2,$3,4
www.random.com,column2,$3,4
example.com/,column2,$3,4
"/"가 포함되지 않은 다른 열을 건드리지 않고 열 1의 모든 URL을 도메인 이름으로 변환해야 합니다. www 이외의 하위 도메인을 유지해야 합니다.
출력은 다음과 같아야 합니다.
example.com,column2,$3,4
unix.random.com,column2,$3,4
example.com,column2,$3,4
example.com,column2,$3,4
example.com,column2,$3,4
example.com,column2,$3,4
unix.random.com,column2,$3,4
example.com,column2,$3,4
example.com,column2,$3,4
random.com,column2,$3,4
example.com,column2,$3,4
어떻게 해야 하나요?
답변1
awk를 사용하십시오.
$ awk 'BEGIN{FS=OFS=","} {sub("^([^/:]+://)?(www[.])?","",$1); sub("/.*","",$1)} 1' file
example.com,column2,$3,4
unix.random.com,column2,$3,4
example.com,column2,$3,4
example.com,column2,$3,4
example.com,column2,$3,4
example.com,column2,$3,4
unix.random.com,column2,$3,4
example.com,column2,$3,4
example.com,column2,$3,4
random.com,column2,$3,4
example.com,column2,$3,4
답변2
나는 이것이 효과가 있다고 믿습니다:
sed -E 's#^(.*://)?(www\.)?##; s#^([^,/]+)[^,]*#\1#'
첫 번째 sed 명령( s#^(.*://)?(www\.)?##
)은 프로토콜 및 "www"와 일치합니다. 그리고 무엇이든 교체하세요. 두 번째 sed 명령( s#^([^,/]+)[^,]*#\1#
)은 첫 번째 슬래시 이전의 모든 항목과 일치한 다음 첫 번째 쉼표 이전의 모든 항목과 일치하고 첫 번째 슬래시 이전의 모든 항목으로 대체하므로 실제로 첫 번째 슬래시에서 첫 번째 쉼표까지 모든 항목이 제거됩니다.
답변3
이는 귀하가 찾고 있는 답변이 아닐 수도 있지만 sed는 운영 체제 간에 일관성이 없을 수 있으며 구문을 읽기도 어렵습니다.
-e
이는 아마도 더 나쁠 수도 있지만 또 다른 옵션은 문자열을 평가하는 플래그 와 함께 명령줄에서 Node.js를 사용하는 것입니다 . 단점은 시스템에 Node.js가 설치되어 있어야 한다는 것입니다.
이 코드는 표준 입력에서 파이프로 연결된 모든 항목을 가져오고 수정된 문자열을 표준 출력으로 인쇄합니다.
cat infile.csv | node -e 'const stdin = process.openStdin();
let data = "";
stdin.on("data", chunk => data += chunk);
stdin.on("end", () => {
console.log(
data
.trim()
.split("\n")
.filter(Boolean)
.map((line) => {
const parts = line.split(",");
const url = new URL((!/^http(s)?\:\/\//.test(line) ? "https://" : "") + parts.shift());
return `${url.host.replace(/^www\./,"")},${parts.join(",")}`
})
.join("\n"))
});' > outfile.csv
당신은 가질 수 있습니다입력 파일을 덮어쓰는 데 문제가 있습니다.그것이 당신이 하고 싶은 일이라면. 이 문제를 해결하려면 파이프를 사용하는 대신 코드 숨김의 매개변수로 파일 이름을 전달할 수 있습니다.
node -e 'const fs = require("fs");
const infile = process.argv[1]; const data = fs.readFileSync(infile).toString();
const output = data
.trim()
.split("\n")
.filter(Boolean)
.map((line) => {
const parts = line.split(",");
const url = new URL((!/^http(s)?\:\/\//.test(line) ? "https://" : "") + parts.shift());
return `${url.host.replace(/^www\./,"")},${parts.join(",")}`
})
.join("\n");
fs.writeFileSync(infile, output)' file.csv
답변4
사용행복하다(이전 Perl_6)
raku -pe 's{ (^ <-[/]>* \/\/ )? (w**3 \.)? (<-[/]>*) <-[,]>* } = "$2";'
[위는 @HatLess의 코드를 번역한 것입니다 sed
].
raku -pe 's{ ^ (.* "://" )? (www\.)? } = ""; s{ ^ (<-[,/]>+) <-[,]>* } = "$0";'
sed
[위는 @D_Bear의 코드를 번역한 것입니다].
출력 예(두 경우 모두):
example.com,column2,$3,4
unix.random.com,column2,$3,4
example.com,column2,$3,4
example.com,column2,$3,4
example.com,column2,$3,4
example.com,column2,$3,4
unix.random.com,column2,$3,4
example.com,column2,$3,4
example.com,column2,$3,4
random.com,column2,$3,4
example.com,column2,$3,4