파일의 특정 줄의 하위 문자열에서 모든 공백을 바꾸는 방법은 무엇입니까?

파일의 특정 줄의 하위 문자열에서 모든 공백을 바꾸는 방법은 무엇입니까?

"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:/'
  1. 행을 h이전 공간에 복사합니다. 나중에 이 줄의 첫 번째 부분에서 사용하겠습니다.
  2. 분할 모드 이전의 모든 항목을 삭제합니다.s/.*(file://
  3. 교체:s/ /%20/g
  4. x첫 번째 부분을 처리할 수 있도록 버퍼를 변경하세요.
  5. 이제 두 번째 부분을 제거하고 패턴으로 시작합니다.s/(file:.*//
  6. G: 첫 번째 부분의 패턴 공간에 두 번째 부분의 예약된 공간을 추가하여 두 부분을 결합합니다.
  7. 이제 삽입을 추가하여 개행 문자를 구분 패턴(두 부분 모두에서 제거함)으로 바꿉니다.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

관련 정보