.txt 파일을 사용하여 fileA의 텍스트 이름을 바꾸려고 합니다 sed
. 두 번째 열은 fileA
제품 이름에 대한 전체 설명입니다. 제품 이름을 제품 ID로 바꾸고 싶습니다. 그러나 설명의 일부 텍스트에는 유사한 내용이 있습니다(예 fileA
: ). "오렌지 주스"는 2행과 4행에 두 번 나타납니다.
renamefile
제품 이름 을 sed
.sed
파일 A:
AB12345 100 0 Apple juice 20/05 AB
CD67890 150 0 Orange juice with pulp 22/05 CS
EF25879 100 0 Watermelon juice 19/05 CG
GH96314 98 0 Orange juice 20/05 PU
IJ74123 95 0 Strawberry juice with lemon 17/05 ST
파일 이름을 바꿉니다.
s/\<Apple juice\>/3071/g
s/\<Orange juice with pulp\>/3072/g
s/\<Orange juice\>/3073/g
s/\<Watermelon juice\>/3074/g
s/\<Apple juice with lemon\>/3075/g
s/\<Strawberry juice with lemon\>/3076/g
현재 출력:
AB12345 100 0 3071 20/05 AB
CD67890 150 0 **3073** 22/05 CS
EF25879 100 0 3074 19/05 CG
GH96314 98 0 3073 20/05 PU
IJ74123 95 0 3076 17/05 ST
원하는 출력:
AB12345 100 0 3071 20/05 AB
CD67890 150 0 3072 22/05 CS
EF25879 100 0 3074 19/05 CG
GH96314 98 0 3073 20/05 PU
IJ74123 95 0 3076 17/05 ST
나는 정확히 일치하는 경우에만 교체에 도움이 된다는 것을 어딘가에서 발견했기 때문에 "<>"를 사용하고 있습니다. 그러나 이 경우에는 작동하지 않는 것 같습니다. (오류는 현재 출력에서 굵게 표시됩니다.)
문자열 교체에서 처음 두 문자열이 일치한 후 더 많은 단어를 고려하고 해당 이름을 해당 ID로 바꾸는 더 좋고 효율적인 방법이 있습니까?
내가 충분히 명확하지 않다면 말해주십시오. 감사해요!
답변1
renamefile
길이를 기준으로 재정렬 해야 하며 긴 이름을 먼저 교체해야 합니다.
awk '{ print length, $0 }' renamefile| sort -nr | cut -d" " -f2- > renamefile2
산출
s/\<Strawberry juice with lemon\>/3076/g
s/\<Orange juice with pulp\>/3072/g
s/\<Apple juice with lemon\>/3075/g
s/\<Watermelon juice\>/3074/g
s/\<Orange juice\>/3073/g
s/\<Apple juice\>/3071/g
그럼 문제없이 신청하실 수 있어요
sed -f renamefile2 fileA
설명하다:
awk
루프 행
length
awk에 내장된 함수입니다. 인수 없이 호출하면 현재 줄의 크기를 인쇄합니다(자세한 내용은이상한 길이)$0
현재 행
다음 명령은 줄 자체 옆에 있는 각 줄의 길이를 인쇄합니다.
awk '{ print length, $0 }' renamefile
24 s/\<Apple juice\>/3071/g
35 s/\<Orange juice with pulp\>/3072/g
25 s/\<Orange juice\>/3073/g
sort
입력된 텍스트가 정렬됩니다.
-n
숫자순으로 정렬됩니다-r
결과가 아래로 향하도록 반전합니다.
cut
텍스트의 일부를 선택합니다(최종 스크립트에서는 길이가 필요하지 않고 sed
줄의 일부만 선택하면 되므로).
-d" "
여기에 구분 기호를 지정합니다space
.-f2-
필드 2부터 라인 끝까지
답변2
/
제품 이름 뒤에 항상 두 자리 숫자, 한 자리 숫자, 다시 두 자리 숫자가 오면 정규식으로 묶고 역참조를 사용하여 그 자체로 바꿀 수 있습니다.
앞의 4개 공백 문자를 일치시켜 해당 문자로 바꿀 수도 있습니다.
파일 이름을 바꿉니다.
s/( {4})Apple juice( [[:digit:]]{2}\/[[:digit:]]{2})/\13071\2/
s/( {4})Orange juice with pulp( [[:digit:]]{2}\/[[:digit:]]{2})/\13072\2/
s/( {4})Orange juice( [[:digit:]]{2}\/[[:digit:]]{2})/\13073\2/
s/( {4})Watermelon juice( [[:digit:]]{2}\/[[:digit:]]{2})/\13074\2/
s/( {4})Apple juice with lemon( [[:digit:]]{2}\/[[:digit:]]{2})/\13075\2/
s/( {4})Strawberry juice with lemon( [[:digit:]]{2}\/[[:digit:]]{2})/\13076\2/
산출:
$ sed -Ef renamefile fileA
AB12345 100 0 3071 20/05 AB
CD67890 150 0 3072 22/05 CS
EF25879 100 0 3074 19/05 CG
GH96314 98 0 3073 20/05 PU
IJ74123 95 0 3076 17/05 ST
답변3
awk를 사용하는 것이 더 쉽습니다.
$ cat tst.awk
BEGIN {
id = 3071
map["Apple juice"] = id++
map["Orange juice with pulp"] = id++
map["Orange juice"] = id++
map["Watermelon juice"] = id++
map["Apple juice with lemon"] = id++
map["Strawberry juice with lemon"] = id++
}
match($0,/^((\S+\s+){3})(.*\S)((\s+\S+){2})/,a) {
$0 = a[1] map[a[3]] a[4]
print
}
$ awk -f tst.awk file
AB12345 100 0 3071 20/05 AB
CD67890 150 0 3072 22/05 CS
EF25879 100 0 3074 19/05 CG
GH96314 98 0 3073 20/05 PU
IJ74123 95 0 3076 17/05 ST
\<
위의 내용은 GNU sed 및 \>
단어 경계를 사용하기 때문에 GNU awk를 사용합니다 .
답변4
GNU sed를 사용하여 먼저 이름 바꾸기 파일을 동적으로 수정한 다음(수동 편집을 수행할 필요가 없음을 의미) 이를 sed 코드로 사용하여 파일 A에서 편집을 수행합니다.
이름이 바뀐 파일에서 변경한 사항은 \> 대신 RHS 경계로 개행을 찾는 것이었습니다. 하지만 그 전에 fileA의 패턴 공간에 개행 문자를 삽입합니다.
$ sed -re '
1i\
s/(\\s+\\S+){2}\\s*$/\\n&/
s/\\>/\\n/
' renamefile | sed -rf - fileA
산출:
AB12345 100 0 3071 20/05 AB
CD67890 150 0 3072 22/05 CS
EF25879 100 0 3074 19/05 CG
GH96314 98 0 3073 20/05 PU
IJ74123 95 0 3076 17/05 ST