.txt
を使用してファイル内のPDFのメタデータを抽出し、各ブックマークの値を整数だけ減らそうとpdftk
します。次の行がBookmarkPageNumber
あります.txt
。
BookmarkBegin
BookmarkTitle: Preface
BookmarkLevel: 1
BookmarkPageNumber: 10
BookmarkBegin
BookmarkTitle: Author
... and so on
これを行うには、sedの代替コマンドを使用しようとしています。これが今まで私が持っているものです。
// $1 is the source .txt file; $2 is the decrement
// __ is a placeholder for the variable with the original value
cat $1 | sed "s/BookmarkPageNumber: [0-9]*/BookmarkPageNumber: `expr __ - $2`/" | cat > metadata.txt
__
元の値を変数に入れてから、同じsed式でプレースホルダをどのように置き換えることができますか?
答え1
これにはawk
算術演算をサポートしているので、使用することをお勧めします。
cat $1 | awk -v d=$2 '/BookmarkPageNumber:/{$2-=d}1'
答え2
awk '!/BookmarkPageNumber:/ {print}; /BookmarkPageNumber:/ {print $1 " " $2-1}' old.txt > new.txt
答え3
別のオプションは、シェル自体を使用することです(たとえば、5を減算したい実際の整数に変更)。
while read key val; do
[[ $key == "BookmarkPageNumber:" ]] && let val=val-5;
echo $key $val;
done < file
または、次のツールを使用できますperl
。
perl -pe 's/(BookmarkPageNumber:\s*)(\d+)$/$1 . ($2-5)/e; ' file
別のアプローチは次のとおりですawk
。
awk '$1~/BookmarkPageNumber:/{$2=$2-5}1;' file
答え4
注:私は彼が最初に読んだ任意の整数でBookmarkPageNumberを減らしたいと思いました。一方、以下の解決策は1万減りました。しかし、努力した結果、完全に除去することは困難です。
--------解決策の一部のみ---------
sedだけを使用したい場合は、次の1行をご覧ください。
sed -r '/^BookmarkPageNumber: /{s/([0-9]*)$/\1@/;:loop {s/0@/@9/;/0@/b loop;};s/1@/_0/;s/2@/_1/;s/3@/_2/;s/4@/_3/;s/5@/_4/;s/6@/_5/;s/7@/_6/;s/8@/_7/;s/9@/_8/;s/ @9+$/ UNDERFLOW/;s/ _0*/ /;s/_//}' $1 >metadata.txt
注:これは自然の10進数でのみ機能します。これが大丈夫です。
ああ、さらにアンダーフロー検出機能もあります。したがって、ページ番号を0に飽和させるには、次のようUNDERFLOW
に置き換えます。0
私はこれが知的妄想にすぎないと言う人の意見に同意します。それはまさにそれだからです。
ps:入出力ファイル記述子が同じファイルを指していることを確認する必要があります。そうしないと、ユーザーに書き込み権限があるとファイルが切り捨てられます。