ファイルの特定の行の部分文字列ですべてのスペースを置き換える方法は?

ファイルの特定の行の部分文字列ですべてのスペースを置き換える方法は?

"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)

2行をどのように接着する必要がありますか? 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. 2番目の部分を削除し、パターンから始めます。s/(file:.*//
  6. G:最初の部分のパターンスペースに2番目の部分の予約済みスペースを追加して2つの部分を結合します。
  7. 挿入を追加して、改行文字を区切りパターン(両方の部分から削除)に置き換えます。s/\n/(file:/

答え2

3番目の引数として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)、次のようにします。
  • 線を空白の前、空白、空白の後の3つの部分に分割します。
  • 最初の部分「%20」と3番目の部分に置き換えます。

このとき、1行に1つのスペースのみが置き換えられるため、ループが必要です。たとえば、

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への2回目の呼び出しは不要ですので、削除してください。

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

関連情報