Sedコマンドを使用して列4からAをRAに置き換えるにはどうすればよいですか? (この列の間には複数のスペースが含まれています。)
ATOM 32 P A 2 6.882 -5.338 6.560 1.00 0.00 P
ATOM 33 OP1 A 2 7.505 -5.970 7.750 1.00 0.00 O
ATOM 34 OP2 A 2 5.404 -5.201 6.610 1.00 0.00 O
TER
合格できるawk '{gsub("A","RA",$4)}1' a.txt > b.txt
答え1
間隔が固定されている必要があるため、これはレイアウト全体が固定されていることを意味します。EREを有効にするには、GNU sedやOSX / BSD sedなどの-Eをサポートするsedを使用します。
$ sed -E 's/(.{17})A /\1RA/' file
ATOM 32 P RA 2 6.882 -5.338 6.560 1.00 0.00 P
ATOM 33 OP1 RA 2 7.505 -5.970 7.750 1.00 0.00 O
ATOM 34 OP2 RA 2 5.404 -5.201 6.610 1.00 0.00 O
TER
または、POSIX sedを使用してください。
$ sed 's/\(.\{17\}\)A /\1RA/' file
ATOM 32 P RA 2 6.882 -5.338 6.560 1.00 0.00 P
ATOM 33 OP1 RA 2 7.505 -5.970 7.750 1.00 0.00 O
ATOM 34 OP2 RA 2 5.404 -5.201 6.610 1.00 0.00 O
TER
編集:入力内容が一致しないようです。PDB標準@bushmanは以前に公開しましたが、そのような場合は、次のようにf[]
ラベル/名前でフィールド配列を作成し、ラベル/名前で変更し(入力の相対位置ではなく)、印刷を使用できます。同じ固定幅フォーマット:
$ cat tst.awk
BEGIN {
# Record Format (copied from http://www.wwpdb.org/documentation/file-format-content/format33/sect9.html#ATOM)
#
# COLUMNS DATA TYPE FIELD DEFINITION
# -------------------------------------------------------------------------------------
flds[++numFlds]=" 1 - 6 Record name ATOM "
flds[++numFlds]=" 7 - 11 Integer serial Atom serial number."
flds[++numFlds]=" 13 - 16 Atom name Atom name."
flds[++numFlds]=" 17 Character altLoc Alternate location indicator."
flds[++numFlds]=" 18 - 20 Residue name resName Residue name."
flds[++numFlds]=" 22 Character chainID Chain identifier."
flds[++numFlds]=" 23 - 26 Integer resSeq Residue sequence number."
flds[++numFlds]=" 27 AChar iCode Code for insertion of residues."
flds[++numFlds]=" 31 - 38 Real(8.3) x Orthogonal coordinates for X in Angstroms."
flds[++numFlds]=" 39 - 46 Real(8.3) y Orthogonal coordinates for Y in Angstroms."
flds[++numFlds]=" 47 - 54 Real(8.3) z Orthogonal coordinates for Z in Angstroms."
flds[++numFlds]=" 55 - 60 Real(6.2) occupancy Occupancy."
flds[++numFlds]=" 61 - 66 Real(6.2) tempFactor Temperature factor."
flds[++numFlds]=" 77 - 78 LString(2) element Element symbol, right-justified."
flds[++numFlds]=" 79 - 80 LString(2) charge Charge on the atom."
for (fldNr=1; fldNr<=numFlds; fldNr++) {
fld = flds[fldNr]
cols = substr(fld,1,16)
gsub(/ /,"",cols)
n = split(cols,begEnd,/-/)
tag = substr(fld,31,13)
gsub(/ /,"",tag)
tags[fldNr] = tag
begs[tag] = begEnd[1]
wids[tag] = begEnd[n] - begEnd[1] + 1
# Uncomment this if interested in the values the arrays contain:
# print "<" fldNr "><" tags[fldNr] "><" begs[tag] "><" wids[tag] ">" | "cat>&2"
}
}
{
for (fldNr=1; fldNr<=numFlds; fldNr++) {
tag = tags[fldNr]
f[tag] = substr($0,begs[tag],wids[tag])
gsub(/^ +| +$/,"",f[tag])
}
}
f["resName"] == "A" { f["resName"] = "RA" } # this is where you can change a field by its tag/name
{
for (fldNr=1; fldNr<=numFlds; fldNr++) {
tag = tags[fldNr]
printf "%-*s", wids[tag], f[tag]
}
print ""
}
$
$ awk -f tst.awk file
ATOM 32 P RA 2 6.882 -5.338 6.560 1.00 0.00 P
ATOM 33 OP1 RA 2 7.505 -5.970 7.750 1.00 0.00 O
ATOM 34 OP2 RA 2 5.404 -5.201 6.610 1.00 0.00 O
TER
明らかに、これは今やっていることに比べて少し過剰ですが、覚えておくべき良い一般的なアプローチであり、関心のある分野について以前に議論した他のアプローチで発生する可能性がある問題を解決します。 。
答え2
使用sed
sed -E "s/^(([^ ]+ +){3})A /\1RA /" file1
牙
入力ラインから始まる^
([^ ] +)
( )
空白以外の文字の連続したシーケンスと、[^ ]+
その後に別の連続した空白文字シーケンスでセットをキャプチャすることを示します。+
このグループの繰り返しをキャッチして、{3}
次の文字が4番目のフィールドに表示されるようにします。
3つの反復をすべてラップしてグループ化します。( )
今保存した「スーパーグループ」\1
の後にA
(たとえば、Aに2つのスペースがある)、次のように置き換えると\1RA
(つまり、末尾のスペースが1つなので、文字数は同じになります)
答え3
列置換を使用して見やすく印刷された表出力を生成するには、コマンドに以下を追加しawk
ます。
awk ' gsub("A","RA",$4){for (i=1;i<=NF;i++){printf("%-9s",$i)}print "" }' a.txt > b.txt
出力はcat b.txt
次のとおりです。
ATOM 32 P RA 2 6.882 -5.338 6.560 1.00 0.00 P
ATOM 33 OP1 RA 2 7.505 -5.970 7.750 1.00 0.00 O
ATOM 34 OP2 RA 2 5.404 -5.201 6.610 1.00 0.00 O
各列間でより具体的な間隔を探している場合は、ループを放棄してprintf
各フィールドに個別の間隔を割り当てる必要があります。
非常に高速な選択肢を探している場合は、sed
いつでも次のようにできます。
sed 's/ A /RA/' a.txt > b.txt
sed
ただし、これにより別のフィールド分割方法が使用されるため、4番目の列だけでなく、ファイル内のすべての「A」が「RA」に置き換えられますawk
。それにもかかわらず、上記のsed
コマンドを使用すると、cat b.txt
次のような結果が表示されます。
ATOM 32 P RA 2 6.882 -5.338 6.560 1.00 0.00 P
ATOM 33 OP1 RA 2 7.505 -5.970 7.750 1.00 0.00 O
ATOM 34 OP2 RA 2 5.404 -5.201 6.610 1.00 0.00 O
答え4
方法 1: 逆参照のない GNU sed
$ sed -re '
h
s/\S+/\n&\n/4
s/\nA\n/RA/;t
g
' file
方法2:逆参照を含むGNU sed。
$ sed -re '
s/^(\s*(\S+\s+){3})(A(\s|$))/\1R\3/
' file
両方のsedソリューションはPosixと互換性がありますが、コードの明確性が犠牲になり、バックスラッシュが発生する可能性があります。
方法3:Perlはawkに似たフィールドを使用しますが、1つの違いは、このフィールドがフィールド値と区切り文字の両方を格納することです。したがって、4番目のフィールドは8番目のフィールドになり、0インデックス配列を使用する場合は7になります。
$ perl -F'/(\S+)/' -lane '
$F[7] =~ s/^A$/RA/;
print @F;\
' file