이것은 작동합니다:
sudo sed 's/good times/bad times/' Chapter1.html > output/Chapter1.html
이것은 작동하지 않습니다:
sudo sed 's/good times/bad times/' Chapter*.html > output/Chapter*.html
이것도 작동하지 않습니다.
sudo sed 's/good times/bad times/' *.html > output/*.html
50개의 챕터가 있으므로 sed에서 와일드카드를 사용하도록 할 수 있나요?
答え1
다른 사람들이 언급했듯이 여기에는 와일드카드뿐만 아니라 루프가 필요합니다.
예를 들어, for
쉘 루프를 사용하여 이를 수행하려면 다음을 수행하십시오.
for f in ./*.html; do
sed 's/good times/bad times/' "$f" > "output/$f"
done
그러면 변수가 f
각 .html 파일 이름으로 설정되어 루프가 반복될 때마다 루프 내에서 코드가 실행됩니다. 단지 ../*.html
*.html
f
명령문 자체에는 for
(값을 설정하는 곳이기 때문에) 간단한 단어가 있지만 $f
변수가 루프 내부에서 사용되는 경우(확장되는 곳이기 때문에)에 주목하세요.
;
변수 확장은 공백 문자나 쉘에 특별한 의미가 있는 기타 문자(예 : , &
, >
및 기타 여러 문자) 가 포함된 경우 스크립트가 손상되지 않도록(또는 더 나쁜 경우) 큰따옴표로 묶습니다 . 변수를 사용할 때 변수를 인용하지 않는 것이 아마도 쉘 스크립트 오류의 가장 큰 원인일 것입니다. 바라보다공백이나 기타 특수 문자 때문에 쉘 스크립트가 멈추는 이유는 무엇입니까?그리고$VAR 대 ${VAR} 및 인용 여부이유를 알아보세요.
원하는 변수 이름을 사용할 수 있습니다.
for Chapter in ./*.html; do
sed 's/good times/bad times/' "$Chapter" > "output/$Chapter"
done
또한 주목할 가치가 있는 것은: 디렉토리에 .html 파일이 없으면 먼저 이 옵션을 활성화하지 않는 한 쉘은 f
(또는 Chapter
)을 리터럴 문자열로 설정합니다 . 에서 :*.html
nullglob
shopt -s nullglob
man bash
nullglob
설정된 경우, bash는 어떤 파일과도 일치하지 않는 패턴(
위의 경로 이름 확장 참조)이 자신이 아닌 빈 문자열로 확장되도록 허용합니다.
그런데 저는 파일 이름이 명령줄 옵션 중 하나로 해석되는 것을 방지하기 위해 루프 ./*.html
와 함께 이것을 사용하고 있습니다.for
*.html
sed
주석에서 @StéphaneChazelas가 언급했듯이 -e
디렉토리에 시작하고 끝나는 파일 이름이 있으면 sed는 이를 실행할 sed 스크립트로 해석합니다. #.html
이런 일이 일어날 가능성은 거의 없지만(배설물과 악의도 마찬가지입니다), 가능한 한 방어적으로 프로그래밍하는 것이 가장 좋습니다.
./*.html
예를 들어 sed 대신 인수를 사용하면 파일 이름이 지정 -e1,$d
되므로 -e1,$d#.html
(완벽하게 유효한 파일 이름) 인수가 ./-e1,$d
sed의 명령줄 옵션 중 하나로 해석되지 않는 것을 볼 수 있습니다. sed 옵션이 에 없습니다 ./
.
또한: $f
로 시작하기 때문에 ./
파일 이름과 같은 출력은 foo.html
으로 리디렉션됩니다 . 경로에 추가 요소가 있어도 여전히 동일한 대상으로 확인되므로 output/./foo.html
이는 완전히 문제가 되지 않습니다 . ./
우스꽝스러운 일조차 output/./././[a million more ./s]/foo.html
그저output/foo.html
GNU sed(Linuxの標準sed)または(ほとんど?)最新バージョンのsedを使用している場合は、次のように--
オプション引数の終わりを指定できます。
for f in *.html; do
sed 's/good times/bad times/' -- "$f" > "output/$f"
done
または両方を実行してください。
for f in ./*.html; do
sed 's/good times/bad times/' -- "$f" > "output/$f"
done
答え2
シェルはコマンドラインでワイルドカード文字を拡張しますが、実行中のコマンドはそれを見ることができず、どうすればよいかわかりません。
したがって、ファイルがあり、a.html
b.html
実行するoutput/b.html
output/c.html
と
sed ... *.html > output/*.html
実際に実行するコマンドは次のとおりです。
sed ... a.html b.html > output/b.html output/c.html
これは構文エラー(2つのファイルにリダイレクトできません)であり、おそらく望むものではありません。
ここで解決策は、forループを使用し、*をループのインデックス変数に置き換えることです。ファイル名にスペースが含まれている場合は、いくつかの引用が必要です。この質問のコピーには、これを正しく実行する方法の多くの例があります。
答え3
ファイルが含まれている作業ディレクトリーにあると仮定すると、以下を使用できます。find
$ find . -name 'Chapter*' -exec sed 's/good times/bad times/woutput/{}' {} 2> /dev/null \;