다음 정보가 포함된 파일이 있습니다.
gene 3025..3855
/gene="Sp34_10000100"
/ID="Sp34_10000100"
CDS join(3025..3106,3722..3855)
/gene="Sp34_10000100"
/codon_start=1
/ID="Sp34_10000100.t1.cds1,Sp34_10000100.t1.cds2"
mRNA 3025..3855
/ID="Sp34_10000100.t1"
/gene="Sp34_10000100"
gene 12640..13470
/gene="Sp34_10000200"
/ID="Sp34_10000200"
CDS join(12640..12721,13337..13470)
/gene="Sp34_10000200"
/codon_start=1
/ID="Sp34_10000200.t1.cds1,Sp34_10000200.t1.cds2"
mRNA 12640..13470
/ID="Sp34_10000200.t1"
/gene="Sp34_10000200"
gene 15959..20678
/gene="Sp34_10000300"
/ID="Sp34_10000300"
CDS join(15959..16080,16268..16367,18913..19116,20469..20524,20582..20678)
/gene="Sp34_10000300"
/codon_start=1
/ID="Sp34_10000300.t1.cds1,Sp34_10000300.t1.cds2,Sp34_10000300.t1.cds3,Sp34_10000300.t1.cds4,Sp34_10000300.t1.cds5"
mRNA 15959..20678
/ID="Sp34_10000300.t1"
/gene="Sp34_10000300"
gene 22255..23085
/gene="Sp34_10000400"
/ID="Sp34_10000400"
모두 삭제하고 싶어요유전자부분적으로는 그렇지만CDS그리고메신저 RNA정보가 거기에 있어야합니다. 출력은 다음과 같아야 합니다.
CDS join(3025..3106,3722..3855)
/gene="Sp34_10000100"
/codon_start=1
/ID="Sp34_10000100.t1.cds1,Sp34_10000100.t1.cds2"
mRNA 3025..3855
/ID="Sp34_10000100.t1"
/gene="Sp34_10000100"
CDS join(12640..12721,13337..13470)
/gene="Sp34_10000200"
/codon_start=1
/ID="Sp34_10000200.t1.cds1,Sp34_10000200.t1.cds2"
mRNA 12640..13470
/ID="Sp34_10000200.t1"
/gene="Sp34_10000200"
CDS join(15959..16080,16268..16367,18913..19116,20469..20524,20582..20678)
/gene="Sp34_10000300"
/codon_start=1
/ID="Sp34_10000300.t1.cds1,Sp34_10000300.t1.cds2,Sp34_10000300.t1.cds3,Sp34_10000300.t1.cds4,Sp34_10000300.t1.cds5"
mRNA 15959..20678
/ID="Sp34_10000300.t1"
/gene="Sp34_10000300"
이 작업을 수행하는 방법에 대한 제안을 알려주십시오.
답변1
awk는 일반적으로 읽고 이해하기가 더 쉽습니다.
이것은 기본적으로 작성하는 간단한 프로그램입니다. 첫 번째 단어가 "gene"인 줄을 보면 "wewrite"를 "0"(= 꺼짐, 쓰지 않음)으로 전환하고 다음과 같은 경우 다시 켜는 것입니다. 그가 본 첫 번째 단어는 "유전자"입니다. 첫 번째 단어가 "CDS" 또는 "mRNA"인 줄을 참조하세요.
awk '
BEGIN { weprint=1 }
( $1 == "gene" ) { weprint=0 }
( $1 == "CDS" ) || ( $1 == "mRNA" ) { weprint=1 }
( weprint == 1) { print $0 ;}
' file_to_read
BEGIN은 행을 읽기 전에 완료됩니다.
다른 하나는 ( test ) { action if test successful }
각 입력 줄을 구문 분석합니다(...작업에 가 포함되어 있지 않으면 next
나머지는 무시하고 대신 다음 입력 줄을 가져옵니다).
이렇게 하면 "유전자" 부분이 아닌 "CDS" 및 "mRNA" 부분만 인쇄됩니다.
이는 "골프 공"일 수 있습니다. 예를 들어 성공적인 "테스트"를 위한 기본 작업은 $0을 인쇄하는 것이므로 ( weprint == 1)
마지막 줄과 같은 작업을 수행할 수 있지만 제 생각에는 이해하기가 덜 명확합니다...)
답변2
sed -e '
/^ *gene /!b # print non-gene block begin lines
:a
$d; N # do-while loop accumulates lines for gene block
s/\n *\///;ta
D # clip the gene block
' yourfile
sed
모델은 파일을 한 줄씩 읽고 지시문이 포함 되지 않는 한 변환 시 sed
해당 섹션의 명령이 -e
해당 줄에 순차적으로 적용된다는 점을 인식해야 합니다 . branching
기본 구문 sed
은 address command
command가 유효한 sed
명령일 수 있고 address
다음 중 하나일 수 있다는 것입니다: linenum
,
$
(= 마지막 줄), regex
, , range of addresses
, 마지막은 모든 줄에 적용된다는 의미는 없습니다. 행은 이름이 지정된 레지스터에 저장됩니다 pattern space
.
따라서 이러한 기본 사항을 마치고 sed
-e
실제 코드로 넘어갑니다.
b
=> sed 코드 끝으로 분기하여 패턴 공간을 인쇄합니다. 즉 , 첫 번째 필드로 !
문자열이 없는(주소 패턴 뒤) 모든 행을 계속 인쇄한다는 의미입니다 .gene
마지막으로 첫 번째 필드 행에 도달하면 gene
do-while 루프( :a
점프할 마커 설정)를 설정하여 패턴 공간 레지스터에 행을 계속 축적합니다( N
다음 행 추가, 줄 바꿈인 s
delete 명령 \n *\/
, 이어서 공백 및 a /
) 두 조건 중 하나가 충족되지 않을 때까지, 즉 eof를 누르거나 => 삭제합니다( $d
=> 마지막 줄에 있으면 패턴 공간을 삭제합니다). 이는 eof 및 Blocks 근처에서 발생하기 때문입니다. 삭제해야 할 유전자
또는 다음 블록의 시작 부분에 도달합니다. s
해당 패턴을 찾아서 제거할 수 있으면 해당 패턴 t
으로 점프하고 :a
, 그렇지 않으면(새 블록이므로 패턴을 찾을 수 없음) 계속합니다. 이제 패턴 공간은 전체 유전자 블록과 다음 블록의 첫 번째 라인을 보유합니다. 우리는 유전자 블록을 즉시 삭제하고 다음 블록의 시작 부분에 있는 sed 코드의 맨 위로 이동합니다(명령이 수행하는 작업입니다 D
).
답변3
나는주는 것을 거부 할 수 없다진주우리가 가끔 대답할 때sed그리고앗답변!
# make perl complain when it should
use strict;
use warnings;
# declare variable
my $section;
# run through every line
while (<>) {
# set the current section to 'gene', 'CDS' or 'mRNA' when it matches
$section = $1 if /^\h*(gene|CDS|mRNA)/;
# print if the current section is not 'gene'
print if $section ne 'gene';
}
답변4
이것은 파일에서 라인 블록을 제거하는 sed 프로그램입니다. 각 블록은 특정 라인 패턴으로 시작하고 다음 블록이 시작되는 곳에서 끝납니다. (이러한 블록을 호출할 수 있습니다.부분, 작업은 sed를 사용하여 섹션을 삭제하는 것입니다. )
이 문제를 해결하기 위한 확실한 시도부터 시작해 보겠습니다(댓글에서 @ Stéphane-Chazelas가 제안한 것과 유사). 그러나 작동하지 않습니다.
sed '/^ gene/,/^ [^ ]/ d'
줄 시작 부분에 공백이 5개 있고 그 뒤에 공백이 없으면 섹션이 끝나고 다음 섹션이 시작됩니다. 우리 섹션은 5개의 공백과 로 시작합니다 gene
.
이 간단한 sed 프로그램의 문제점은 주소 범위가 다음 섹션의 시작 줄과도 일치하여 이를 삭제한다는 것입니다.
하지만 이것은 작동합니다:
end='^ [^ ]'
begin='^ gene'
sed --regexp-extended -e "/$begin/,/$end/ {
/$end/! d # skip the end, otherwise delete
/$begin/ d # do not skip (even if it happens to match end)
}" \
-i -- "$@"
귀하의 예에서 이것을 시도하면 원하는 결과를 얻을 수 있습니다.
$ cp example-stackexchange-360117.txt{.orig,} -vf
'example-stackexchange-360117.txt.orig' -> 'example-stackexchange-360117.txt'
$ ./delete-section2-gene example-stackexchange-360117.txt
$ diff example-stackexchange-360117.txt{.orig,}
1,3d0
< gene 3025..3855
< /gene="Sp34_10000100"
< /ID="Sp34_10000100"
11,13d7
< gene 12640..13470
< /gene="Sp34_10000200"
< /ID="Sp34_10000200"
21,23d14
< gene 15959..20678
< /gene="Sp34_10000300"
< /ID="Sp34_10000300"
31,33d21
< gene 22255..23085
< /gene="Sp34_10000400"
< /ID="Sp34_10000400"
$
일치하는 후속 행이 없더라도 파일 끝의 마지막 부분을 마술처럼 제거한다는 점에 유의하세요 $end
! (이유는 GNU sed 매뉴얼에서 명확하지 않습니다.)
비슷한 문제가 있었는데, 이에 대해 다음 해결책을 생각해 냈습니다. Python 소스에서 전체 함수 정의를 제거합니다.라이브러리/테스트/audit-tests.pyPython 3.8.1 소스에서.
다른 모드로 동일한 스크립트를 사용합니다.
end='^[^[:blank:]]'
begin='^def .*winreg'
sed --regexp-extended -e "/$begin/,/$end/ {
/$end/! d # skip the end, otherwise delete
/$begin/ d # do not skip (even if it happens to match end)
}" \
-i -- "$@"
들여쓰기가 다시 최상위 레벨인 곳에서 끝나는 함수 정의를 훌륭하게 제거합니다(즉, 다음 섹션은 들여쓰기 0에서 시작합니다).
$ git checkout 3.8
$ ../delete-section2 Lib/test/audit-tests.py
$ git --no-pager diff
diff --git a/Lib/test/audit-tests.py b/Lib/test/audit-tests.py
index 33f320992b..ed08612c04 100644
--- a/Lib/test/audit-tests.py
+++ b/Lib/test/audit-tests.py
@@ -304,29 +304,6 @@ def test_unraisablehook():
write_unraisable_exc(RuntimeError("nonfatal-error"), "for audit hook test", None)
-def test_winreg():
- from winreg import OpenKey, EnumKey, CloseKey, HKEY_LOCAL_MACHINE
-
- def hook(event, args):
- if not event.startswith("winreg."):
- return
- print(event, *args)
-
- sys.addaudithook(hook)
-
- k = OpenKey(HKEY_LOCAL_MACHINE, "Software")
- EnumKey(k, 0)
- try:
- EnumKey(k, 10000)
- except OSError:
- pass
- else:
- raise RuntimeError("Expected EnumKey(HKLM, 10000) to fail")
-
- kv = k.Detach()
- CloseKey(kv)
-
-
if __name__ == "__main__":
from test.libregrtest.setup import suppress_msvcrt_asserts
$
b
명령("branch")을 사용하는 이 sed 프로그램의 변형 :
end='^[^[:blank:]]'
begin='^def .*winreg'
sed --regexp-extended -e "/$begin/,/$end/ {
/$begin/ d # delete, do not skip
/$end/ b # skip
d # default action
}" \
-i -- "$@"