すべての列ヘッダーがパス名であるファイルがあります。各列ヘッダーを短くしたいと思います。~から次のようなもの:
/mydir/cat/dog/hen/test/block/sample1.so.rg.mk.bam /mydir/cat/dog/hen/test/block/sample2.so.rg.mk.bam
到着する:
sample1 sample2
Linuxでこれを行うにはどうすればよいですか?私のファイルには46〜100を超える列があるため、列名を手動で編集することはできません。私が望むファイル名の長さは、上記のようにそれぞれ7文字です。
ありがとう
ヘッダーにはファイル名が含まれます。各列ヘッダー/名前は次のとおりです。
/mydir/cat/dog/hen/test/block/sample1.so.rg.mk.bam
私はその場にいたらいいのに
sample1
明確にするために、これは46列のテキストファイルです。各列ヘッダーまたは名前は、上記の長い文字列で表されます。各ヘッダーを7文字のバージョンに切りたいと思います。「サンプル1」…「サンプル46」
必須サンプルファイル(各列ヘッダーの下にデータを含む)
sample1 sample2 sample3 sample4 sample5 ...
答え1
元のファイルを短い名前の新しいファイルにコピーする短いプログラムを作成します。元のファイルをアーカイブすると、問題が発生した場合にバックアップが可能になります。作成する内容は、おなじみの言語によって異なります。これはBashのようなシェルでも、Java、C、Pearl、Pythonなどのすべての言語でもかまいません。
以下はいくつかの疑似コードです。 old は元のファイル、new は新しいファイルです。新規
begin a loop to read each line in old
read line from old
delete all characters from line up to and including the last "/"
delete delete all characters from line after the first 7
//This is what you want to save unless it conflicts with a previously saved line
determine if you have a conflict.
if there is a conflict
add a number to the end of line to make it unique
save line to new
end of loop
答え2
4つの列と2つの行を持つファイルがあるとしましょう。
host:~ # cat file2
/mydir/cat/dog/hen/test/block/sample1.so.rg.mk.bam /mydir/cat/dog/hen/test/block/sample2.so.rg.mk.bam /mydir/cat/dog/hen/test/block/sample3.so.rg.mk.bam /mydir/cat/dog/hen/test/block/sample4.so.rg.mk.bam
abc def ghi jkl
このコマンドは私にとって効果的です(非常に便利ではありませんが、それでも)。
host:~ # sed -i -e 's/^\///g' -e 's/[[:alnum:]]\+\///g' -e 's/\.[[:alnum:]]\+//g' -e 's/\///g' file2
host:~ # cat file2
sample1 sample2 sample3 sample4
abc def ghi jkl
より効率的な方法があると確信していますが、試してみることができます。
答え3
不要なサフィックスは常にあると仮定します。「.so.rg.mk.bam」、その後牛に似た一種の栄養 sed
~のe
評価注文するbasename
最初の行でのみ実行するために使用できますファイル名、希望の出力に置き換えます。
sed -i '1s/.*/basename -as .so.rg.mk.bam -a &/e' filename
~のためGNUではない sed
sをhead
代わりに使用できます。
sed -i '1s/.*/'"$(basename -as .so.rg.mk.bam -a $(head -1 filename))"'/' filename
-
注:ファイルを変更せずに結果を表示するには、まずファイルを変更せずに試してください-i
。
答え4
awkを使用してヘッダーを処理できます。次のawkスクリプトが機能しますただ最初の行(NR==1
)。行のすべてのフィールドを一度に繰り返します。各フィールドに対して次の手順を実行します。
- テキストの最初のインスタンスを見つけて、その
/sample
インスタンスにテキストを切り取ります(および渡す/
)。 - 期間の残りの部分で最初のインスタンスを見つけ、その期間から始めてその部分をクリーンアップします。
- 残りの部分が長すぎる場合は、
sample
必要に応じてテキストを切り取ります。どれくらい保持すべきかについての方程式は、「6プラスの最初の数字の位置 - 全長」です。 - フィールドを処理した後、末尾のスペースを含む印刷します。
- すべてのフィールドの反復が終了すると、改行文字を印刷します。
これにより、行の末尾に末尾のスペースが残ります。
awkスクリプト:
NR == 1 {
for(i=1; i <= NF; i++) {
tail=substr($i, 1 + match($i, "/sample")) # delete up to the first instance of "/sample"
tail=substr(tail, 1, index(tail, ".") - 1) # find, then stop short of, the first period
if (length(tail) > 7) { # if it's too long
match(tail, "[0-9]") # find the first digit
# trim the beginning down, then append the number
tail=substr(tail, 1, 6 + RSTART - length(tail))substr(tail, RSTART)
}
printf tail" "
}
print ""
}
サンプル入力:
/mydir/cat/dog/hen/test/block/sample1.so.rg.mk.bam /mydir/cat/dog/hen/test/block/sample47.so.rg.mk.bam /mydir/cat/dog/hen/test/block/sample4631.so.rg.mk.bam /mydir/cat/dog/hen/test/block/sample1234567.so.rg.mk.bam
出力例は次のとおりです。
sample1 sampl47 sam4631 1234567