몇백만 줄만 있는 파일이 있는데 모두 똑같습니다. 한 가지 예를 들면 다음과 같습니다.
Known
Known
Known
Known
Known
Known
...
수천 개의 줄 번호가 포함된 또 다른 파일이 있습니다. 예를 들면 다음과 같습니다.
3
5
6
...
UnKnown과 같은 bash 명령을 사용하여 이 줄을 다른 문자열로 바꾸는 빠른 방법이 있는지 궁금합니다. 생성하려는 예를 기반으로 다음을 수행합니다.
Known
Known
UnKnown
Known
UnKnown
UnKnown
...
답변1
해결책 awk
:
$ awk 'NR==FNR{a[$1]++;next}
{
if(FNR in a){
print "UnKnown"
}
else{
print
}
}' nums file
Known
Known
UnKnown
Known
UnKnown
UnKnown
설명하다
NR==FNR{a[$1]++;next}
:는NR
입력의 현재 줄 번호이고FNR
현재 파일의 현재 줄 번호입니다. 둘은 첫 번째 파일을 읽을 때만 동일합니다. 따라서 이 표현식은$1
각 줄 번호(첫 번째 파일의 첫 번째 필드)를 배열의 키로 저장한a
후 다음 줄로 이동합니다.if(FNR in a){ print "UnKnown"}
: 현재 파일의 줄 번호가 첫 번째 파일에 있으면 "UnKnown"을 인쇄합니다.else {print}
: 그렇지 않은 경우 현재 행을 인쇄합니다.
답변2
이는 "변경할 행 수가 적은 경우" 시나리오에 대한 Giles의 답변의 변형입니다. 인라인 sed 표현식을 작성하는 대신 -f -를 사용하여 읽기 위해 stdout/stdin을 통해 sed로 파이프되는 sed 스크립트를 만듭니다. 이렇게 하면 명령줄 길이 제한과 관련된 문제를 피할 수 있습니다. 또는 sed 스크립트를 "temp" 파일에 저장하고 sed가 해당 파일을 가리킬 수 있습니다.
제가 소개한 또 다른 변형은 sed의 "c" 명령입니다. 이는 선택한 줄을 주어진 텍스트로 바꾸는 것을 의미합니다. "c" 명령의 구문은 백슬래시, 개행, 새 텍스트가 필요하다는 점에서 약간 특이합니다.
sed 's/$/c\\\nNew String/' line-number-file | sed -f - input-file > output-file
$
첫 번째 sed 명령은 줄 끝( )을 "c, 백슬래시, 개행, 새 문자열" 시퀀스로 "대체"하여 두 번째 sed에 대한 입력으로 중간 sed 스크립트를 만듭니다 .
3c\
New String
5c\
New String
6c\
New String
대체 텍스트로 사용된 텍스트를 변경하려면 첫 번째 sed 섹션으로 이동하여 "New String"을 원하는 것으로 바꾸십시오.
원본 입력 파일의 텍스트를 바꾸고 sed가 해당 -i
플래그를 지원하는 경우 명령을 다음과 같이 변경할 수 있습니다.
sed 's/$/c\\\nNew String/' line-number-file | sed -f - -i input-file
답변3
한 가지 가능성은 awk를 통해 행을 필터링하는 것입니다. 변경하려는 줄 목록이 작으면 명령줄에서 awk에 전달하세요.
awk <original.txt >modified.txt -v lines="$(cat lines-to-change.txt)" '
BEGIN {split(lines, a); for (i in a) change[a[i]]=1}
NR in change {$0 = "Un" $0} # or $0 = "UnKnown"
1
'
변경할 줄 수가 매우 적고 수정할 파일이 매우 큰 경우 sed가 더 빠를 수 있습니다. sed를 사용하면 각 줄에 적용하려는 대체 항목이 포함된 스크립트를 작성해야 합니다.
sed "$(<lines-to-change.txt sed 's/$/s:^:Un:/')" <original.txt >modified.txt
행의 많은 부분을 변경해야 하는 경우 처음 두 가지 방법을 사용하면 명령줄 길이 제한이 발생합니다. 이는 두 개의 파일을 병렬로 읽는 awk의 수정입니다. 이미 정렬되어 있으면 대신 lines-to-change.txt
사용할 수 있습니다 .getline n <"lines-to-change.txt"
"sort -n lines-to-change.txt" | getline n
awk <original.txt >modified.txt '
BEGIN {"sort -n lines-to-change.txt" | getline n}
NR==n {$0 = "Un" $0; n = 0; "sort -n lines-to-change.txt" | getline n}
1
'