"journal/*.md"라는 이름의 Markdown 파일이 3000개 있는데 그 중 일부에는 다음과 같은 파일 링크가 포함되어 있습니다.
blah blah text [Label here](file:///path/to file/may contain/spaces)
file:// URL에 %20을 포함하도록 해당 파일의 모든 행을 변경하고 싶습니다.
blah blah text [Label here](file:///path/to%20file/may%20contain/spaces)
스토브 파이프를 통해 거의 다 도착했습니다.
for file in */*md; do if grep -l '(file:.*[ ].*)' "$file"; then echo FOUND in $file; sed 's?\((file://.*[ ].*)\)?\nREPLACED_SED1 \1?g' "$file" > "$file".sed1; sed '/REPLACED_SED1/s/ /%20/g' "$file".sed1 > "$file".sed2; fi; done
이렇게 하면 행이 다음과 같이 분할된 Frankenfile이 생성됩니다.
blah blah text [Label here]
REPLACED_SED1(file:///path/to%20file/may%20contain/spaces)
두 줄을 어떻게 접착해야 합니까? Perl을 구출하시겠습니까?
감사해요!
답변1
줄의 일부에만 교체를 적용하려면 예약된 공간을 사용하여 한 번 실행해 보는 것이 좋습니다.
sed 'h;s/.*(file://;s/ /%20/g;x;s/(file:.*//;G;s/\n/(file:/'
- 행을
h
이전 공간에 복사합니다. 나중에 이 줄의 첫 번째 부분에서 사용하겠습니다. - 분할 모드 이전의 모든 항목을 삭제합니다.
s/.*(file://
- 교체:
s/ /%20/g
x
첫 번째 부분을 처리할 수 있도록 버퍼를 변경하세요.- 이제 두 번째 부분을 제거하고 패턴으로 시작합니다.
s/(file:.*//
G
: 첫 번째 부분의 패턴 공간에 두 번째 부분의 예약된 공간을 추가하여 두 부분을 결합합니다.- 이제 삽입을 추가하여 개행 문자를 구분 패턴(두 부분 모두에서 제거함)으로 바꿉니다.
s/\n/(file:/
답변2
세 번째 인수로 GNU awk를 사용하십시오 match()
.
$ awk 'match($0,/(.*\(file:)(.*)(\).*)/,a) { gsub(/ /,"%20",a[2]); $0=a[1] a[2] a[3] } 1' file
blah blah text [Label here](file:///path/to%20file/may%20contain/spaces)
match()
+와 함께 awk를 사용하여 동일한 작업을 수행할 수 있습니다. substr()
문자 몇 개만 더 입력하면 됩니다.
$ awk 'match($0,/\(file:.*\)/) { tgt=substr($0,RSTART,RLENGTH); gsub(/ /,"%20",tgt); $0=substr($0,1,RSTART-1) tgt substr($0,RSTART+RLENGTH) } 1' file
blah blah text [Label here](file:///path/to%20file/may%20contain/spaces)
답변3
노력하다:
for file in */*md; do
while grep -l '(file:.*[ ].*)' "$file"; do
sed -i 's/\(.*file:[^)]*\) \(.*\)/\1%20\2/' "$file"
done
done
설명하다:
- 파일 이름에 공백이 있는 경우(자신의 grep) 다음을 수행하십시오.
- 선을 공백 전, 공백, 공백 후의 세 부분으로 나눕니다.
- 첫 번째 부분 "%20"과 세 번째 부분으로 바꿉니다.
이때 한 줄에 하나의 공백만 교체되므로 루프가 필요합니다. 예를 들어:
input: blah blah text [Label here](file:///path/to file/may contain/spaces)
1st iteration: blah blah text [Label here](file:///path/to file/may%20contain/spaces)
2nd iteration: blah blah text [Label here](file:///path/to%20file/may%20contain/spaces)
답변4
코드를 조정하고 sed에 대한 두 번째 호출은 불필요하므로 제거하세요.
for f in ./*/*md; do
# select a nonlinked, regular, nonempty file
[ ! -L "$f" ] &&
[ -f "$f" ] &&
[ -s "$f" ] &&
< "$f" grep -q '(file://.*[ ].*)' ||
continue
echo "FOUND in $f"
sed -e ':a
s#\((file://.*\)[ ]\(.*)\)#\1%20\2#
t a
' < "$f" > "$f.modif" &&
mv -f "$f.modif" "$f"
done