meta.txt
次の情報を含むテキストファイルがあります。
という別のものがあります。data
output_folder = "data"
conv
以下のように関数の内部に名前が付けられた関数を実行するには、ofでパスルックアップを使用してsystem
ファイルを次のように変換します。fastq.gz
2nd column
meta.txt
fastq.gz
fastq.txt
tail -n+2 meta.txt | awk -v output_folder=${output_folder} '{ system("convert " $2 $output_folder/"fastq.txt") }'
しかし、最終的に次のエラーが発生しました。
awk: cmd. line:1: (FILENAME=- FNR=1) fatal: division by zero attempted
ベストアンサー1
awkは、他のツールを順番に呼び出すツールではなく、テキストを操作するためのツールです。これがシェルの目的です。テストするテキスト入力/出力を提供していないので、これはテストされていないと思いますが、コードで実行したいのは次のシェルループだけです(IFS
設定または変更されていないと仮定)。
while read -r _ file; do
convert "$file" "$output_folder/fastq.txt"
done < <(tail -n +2 meta.txt)
何らかの理由で呼び出しにawkを使用したい場合は、convert
次のようにします。
output_folder="$output_folder" \
awk '
BEGIN { outfold = ENVIRON["output_folder"] }
NR>1{ system("convert \047" $2 ("\047 \047" outfold "/fastq.txt\047") }
' meta.txt
ただし、これはsystem()が呼び出されるたびにサブシェルを生成するため、awkを使用して利点を得るには遅すぎます。
バラよりawkスクリプトでシェル変数を使用する方法ENVIRON[]
awkバリアントがENVIRON[]
。
ゼロ除算エラーが発生する理由は、内部コードは次のとおりですsystem()
。
"convert " $2 $output_folder/"fastq.txt"
数値ではなく文字列を含めることoutput_folder
ができるため、実行するとgawk --lint
次の警告メッセージが表示されます。
warning: attempt to field reference from non-numeric value
/
それに対して、しかしリテラル文字列が続く除算演算子があります"fastq.txt"
。この文字列が数値として扱われる場合(この例のように)0に等しいので、「0で除算」です。
あなたのコメントと更新された質問について:
質問でこの機能を変更してください。
function convert {
INPUT=$1
OUTPUT=$2
INPUT_R=0
if [ "${INPUT: -3}" == ".gz" ]; then
INPUT_S=1
fi
if [[ $INPUT_R -eq 1 ]]; then
gunzip -c ${INPUT} > ${OUTPUT}
else
cp -v ${INPUT} ${OUTPUT}
fi
chmod ug+rw ${OUTPUT}
}
問題を解決します(一部http://shellcheck.netあなたに言うでしょう - シェルにもっと慣れるまで、常にスクリプトでこれを実行してください):
#!/usr/bin/env bash
convert() {
local input=$1 output=$2
if [[ $input = *.gz ]]; then
gunzip -c -- "$input" > "$output"
else
cp -v -- "$input" "$output"
fi &&
chmod -- ug+rw "$output"
}
output_folder='/Users/doc'
# now include this:
while read -r _ file; do
convert "$file" "$output_folder/fastq.txt"
done < <(tail -n +2 meta.txt)
# or this at the end of the same script:
export -f convert # only works if sh is bash in your env since
# system() will call sh to run the command
output_folder="$output_folder" \
awk '
BEGIN { outfold = ENVIRON["output_folder"] }
NR>1{ system("convert \047" $2 ("\047 \047" outfold "/fastq.txt\047") }
' meta.txt
awkがサブシェルから関数を呼び出せるようにするには、関数をエクスポートする必要があります。使用したい出力ファイルが書き込み可能でない理由を自分で特定する必要がありますが、簡単です。
〜のようにスティーブン・チャジェラスコメントに記載されているように(現在実施されている上記の他のコメントに感謝します):
- ファイルパスに文字が含まれていないという保証がない場合は、
'
任意のコマンドインジェクションの脆弱性と同じです。 - これは
\47
ASCIIベースのシステムを想定しています(現在は比較的安全な仮定)。 chmod ug+rw
これをゼロに変更すると、これを防ぐことができますumask
(しかし、ワールドファイルを書き込み可能にするのはとにかく悪い考えのように聞こえます)。