Linux命令行文本操作一文就夠

原創:熊+jimmy+SX 生信技能樹

主要是awk/grep/sed這三駕馬車,加上vi這個神器,最后輔助一些小工具,包括 wc,cat,diff,join,paste,cut,uniq

這里簡要地整理下Linux用來處理數據文本的工具。具體命令詳情請在Linux命令大全中搜索或者查閱其他相關資料。

head, tail查看文檔頭尾,-n選項可以指定行數。

less用來查閱文檔, q退出, space bar翻頁, g第一行, G最后一行, j下, k上,/<pattern>往下搜索模式, ?<pattern>往上搜索模式, n前一個匹配字符, N后一個匹配字符。

less可以用于debug,查看中間輸出結果。比如

step1 input.txt | step2 | step3 > output.txt   # step1,2,3為程序或命令名

可以寫成

step1 input.txt | less
step1 input.txt | step2 | less
step1 input.txt | step2 | step3 | less

這樣就可以一步步的查看中間結果啦~

用man可以查看less的詳細手冊,注意兩個參數即可,分別是 -S(可以比較規整地查看內容)和 -N(查看內容每行加相應地行數)。

同理還有 more 命令, cat 命令也可以查看文本。

純文本信息匯總

文件行數

wc命令默認依次輸出單詞數、行數、總字符數。查看行數使用 wc -l。 如果存在空行,空行會被計數。可以使用grep命令實現非空行計數 grep -c "[^ \\n\\t]" some_data.bed

ls -lh以易讀形式查看文件大小。

文件列數

# -F指定分隔符,此處假定是table鍵分隔,默認空格鍵
awk -F "\t" '{print NF; exit}' some_data.bed

去除注釋的元數據行? 計數非注釋行行數?

可以使用 tail結合 awk,以gtf(基因組注釋文件)為例

(zzz) [zzz@gpu01 mm10]$ head -8 Mus_musculus.GRCm38.84.gtf 
#!genome-build GRCm38.p4
#!genome-version GRCm38
#!genome-date 2012-01
#!genome-build-accession NCBI:GCA_000001635.6
#!genebuild-last-updated 2016-01
1   havana  gene    3073253 3074322 .   +   .   gene_id "ENSMUSG00000102693"; gene_version "1"; gene_name "4933401J01Rik"; gene_source "havana"; gene_biotype "TEC"; havana_gene "OTTMUSG00000049935"; havana_gene_version "1";
1   havana  transcript  3073253 3074322 .   +   .   gene_id "ENSMUSG00000102693"; gene_version "1"; transcript_id "ENSMUST00000193812"; transcript_version "1"; gene_name "4933401J01Rik"; gene_source "havana"; gene_biotype "TEC"; havana_gene "OTTMUSG00000049935"; havana_gene_version "1"; transcript_name "4933401J01Rik-001"; transcript_source "havana"; transcript_biotype "TEC"; havana_transcript "OTTMUST00000127109"; havana_transcript_version "1"; tag "basic"; transcript_support_level "NA";
1   havana  exon    3073253 3074322 .   +   .   gene_id "ENSMUSG00000102693"; gene_version "1"; transcript_id "ENSMUST00000193812"; transcript_version "1"; exon_number "1"; gene_name "4933401J01Rik"; gene_source "havana"; gene_biotype "TEC"; havana_gene "OTTMUSG00000049935"; havana_gene_version "1"; transcript_name "4933401J01Rik-001"; transcript_source "havana"; transcript_biotype "TEC"; havana_transcript "OTTMUST00000127109"; havana_transcript_version "1"; exon_id "ENSMUSE00001343744"; exon_version "1"; tag "basic"; transcript_support_level "NA";

可以看到注釋行是5行,我們利用tail試試去掉它

# 注意此處 -n后接的"+"號
(zzz) [zzz@gpu01 mm10]$ tail -n +6 Mus_musculus.GRCm38.84.gtf | head -n 1
1   havana  gene    3073253 3074322 .   +   .   gene_id "ENSMUSG00000102693"; gene_version "1"; gene_name "4933401J01Rik"; gene_source "havana"; gene_biotype "TEC"; havana_gene "OTTMUSG00000049935"; havana_gene_version "1";

成功搞定,然后結合前面提到的 awk命令即可計算行數。

上面方法robust不夠(人為地確定行數),更為通用的方法是 grep結合 awk命令

(zzz) [zzz@gpu01 mm10]$ grep -v "^#" Mus_musculus.GRCm38.84.gtf | head -n 1
1   havana  gene    3073253 3074322 .   +   .   gene_id "ENSMUSG00000102693"; gene_version "1"; gene_name "4933401J01Rik"; gene_source "havana"; gene_biotype "TEC"; havana_gene "OTTMUSG00000049935"; havana_gene_version "1";

cut詳解

cut可以處理列數據, -f選項指定列,可以是一個范圍(比如2-8),注意不能用它給列排序

(zzz) [zzz@gpu01 mm10]$ grep -v "^#" Mus_musculus.GRCm38.84.gtf | head -n 10 | cut -f 3
gene
transcript
exon
gene
transcript
exon
gene
transcript
exon
exon
(zzz) [zzz@gpu01 mm10]$ grep -v "^#" Mus_musculus.GRCm38.84.gtf | head -n 10 | cut -f 3-5
gene    3073253 3074322
transcript  3073253 3074322
exon    3073253 3074322
gene    3102016 3102125
transcript  3102016 3102125
exon    3102016 3102125
gene    3205901 3671498
transcript  3205901 3216344
exon    3213609 3216344
exon    3205901 3207317

-d選項可以指定分隔符,比如 -d,指定 ,為分隔符。

使用 column命令來格式化輸出,上次的命令結果輸出明顯沒對齊,我們把它對齊看看:

(zzz) [zzz@gpu01 mm10]$ grep -v "^#" Mus_musculus.GRCm38.84.gtf | head -n 10 | cut -f 3-5 | column -t
gene        3073253  3074322
transcript  3073253  3074322
exon        3073253  3074322
gene        3102016  3102125
transcript  3102016  3102125
exon        3102016  3102125
gene        3205901  3671498
transcript  3205901  3216344
exon        3213609  3216344
exon        3205901  3207317

使用這個命令是為了好觀察,不要把用它處理然后把結果傳入文本(會導致程序處理文件效率降低,因為文本解析速度會下降)。
cutcolumn默認以 \t為分隔符,這里也能夠用 -s選項指定
先把之前的tab分隔文件弄成逗號分隔文件,然后使用 -s選項看看:

(zzz) [zzz@gpu01 mm10]$ grep -v "^#" Mus_musculus.GRCm38.84.gtf | head -n 10 | cut -f 3-5 | awk '{FS="\t";OFS=",";}{print $1,$2,$3}'
gene,3073253,3074322
transcript,3073253,3074322
exon,3073253,3074322
gene,3102016,3102125
transcript,3102016,3102125
exon,3102016,3102125
gene,3205901,3671498
transcript,3205901,3216344
exon,3213609,3216344
exon,3205901,3207317

(zzz) [zzz@gpu01 mm10]$ grep -v "^#" Mus_musculus.GRCm38.84.gtf | head -n 10 | cut -f 3-5 | awk '{FS="\t";OFS=",";}{print $1,$2,$3}'| column -s "," -t
gene        3073253  3074322
transcript  3073253  3074322
exon        3073253  3074322
gene        3102016  3102125
transcript  3102016  3102125
exon        3102016  3102125
gene        3205901  3671498
transcript  3205901  3216344
exon        3213609  3216344
exon        3205901  3207317

簡單了解grep

grep處理速度非常之快,能用它盡量用它。 --color=auto可以激活顏色(標記匹配文字),更方便查看。

-v選項排除匹配到的, -w進行完全匹配。這樣可以防止,你想排除 abc結果把 abc1, abcd也排除掉了。

-B指定輸出包括匹配到的前多少行,比如 -B1就是前一行;
-A指定輸出包括匹配到的后多少行,比如 -A2就是包括了后兩行;
-C指定輸出包括匹配到的前后多少行;
grep支持基本正則表達式;
-E指定支持擴展表達式,或者用 egrep命令;
-c選項對匹配的行計數;
-o選項只抽離輸出匹配的部分。

(zzz) [zzz@gpu01 mm10]$ grep -E -o 'gene_id "\w+"' Mus_musculus.GRCm38.84.gtf | head -n 5
gene_id "ENSMUSG00000102693"
gene_id "ENSMUSG00000102693"
gene_id "ENSMUSG00000102693"
gene_id "ENSMUSG00000064842"
gene_id "ENSMUSG00000064842"

發現冗余項非常多,如果我們只要唯一的呢,怎么辦?

[zzz@gpu01 mm10]$ grep -E -o 'gene_id "\w+"' Mus_musculus.GRCm38.84.gtf| cut -d " " -f 2| sed 's/"http://g' | sort | uniq| head -n 10
ENSMUSG00000000001
ENSMUSG00000000003
ENSMUSG00000000028
ENSMUSG00000000031
ENSMUSG00000000037
ENSMUSG00000000049
ENSMUSG00000000056
ENSMUSG00000000058
ENSMUSG00000000078
ENSMUSG00000000085

(zzz) [zzz@gpu01 mm10]$ grep -E -o 'gene_id "\w+"' Mus_musculus.GRCm38.84.gtf| cut -d " " -f 2| sed 's/"http://g' | sort -u| head -n 10 
ENSMUSG00000000001
ENSMUSG00000000003
ENSMUSG00000000028
ENSMUSG00000000031
ENSMUSG00000000037
ENSMUSG00000000049
ENSMUSG00000000056
ENSMUSG00000000058
ENSMUSG00000000078
ENSMUSG00000000085
#這倆命令等價

file查看文件編碼

(zzz) [zzz@gpu01 mm10]$ file GRCm38.84.id2biotype.txt 
GRCm38.84.id2biotype.txt: ASCII text

常用的大型數據文件一般存為ASCII碼形式(像幾大基因bank的數據文件),而我們自己認為創建的常為UTF-8,所以有時候認為處理文件需要會碰到把UTF-8編碼的字符插入到ASCII碼文件里去了。遇到這種問題,我們可以用 hexdump -c命令查看出錯的地方

sort對文本排序

先創建一個bed格式文件:

(zzz) [zzz@gpu01 mm10]$ cat > test.bed
chr1    26  39
chr3    32  47
chr1    40  50
chr1    9   28
chr2    35  54
chr1    10  19
^Z
[5]+  Stopped                 cat > test.bed
(zzz) [zzz@gpu01 mm10]$ sort test.bed 
chr1    10  19
chr1    26  39
chr1    40  50
chr1    9   28
chr2    35  54
chr3    32  47

可以明顯看到文本按照第一列進行了排序。 默認, sort用空格或tab鍵作為域(列)分隔符。如果我們用其他形式的分隔符,需要用 -t選項指定。

下面是對 bed文件最通用的排序命令:

(zzz) [zzz@gpu01 mm10]$  sort -k1,1 -k2,2n test.bed 
chr1    9   28
chr1    10  19
chr1    26  39
chr1    40  50
chr2    35  54
chr3    32  47

bedtools軟件都會先用這個命令對bedtools文件排序。
-k選項指定某列的排序方式。而每次使用 -k選項都要帶上指定列的范圍(start, end)。如果只指定一列,就為(start,start)了,像上面命令的 -k1,1就是。也許你會覺得 -k2,2n很奇怪,這里的n指定程序把第二列當做數值對待。如果不做設定,都是當做字符對待(shell都是這么對待數值數據的)。所以總結其他這一行命令就是對第一列按照字符排序,第二列按照數值排序。

我們可以用 -c選項檢查一個文件是不是已經按照過某種方式排過序了,一般shell返回0表示成功執行。

反向排序用-r選項。如果你只想反轉一列,可以把它加在 -k選項后。

sort -k1,1 -k2,2nr test.bed
chr1    40  50
chr1    26  39
chr1    10  19
chr1    9   28
chr2    35  54
chr3    32  47

現在我給 test.bed加一行:

cat test.bed
chr1    26  39
chr3    32  47
chr1    40  50
chr1    9   28
chr2    35  54
chr1    10  19
chr11    22  56

你會發現有點奇怪

sort -k1,1 -k2,2n test.bed
chr1    9   28
chr1    10  19
chr1    26  39
chr1    40  50
chr11    22  56
chr2    35  54
chr3    32  47

怎么 chr11在 chr2前面?其實 sort排序的方式有點像查字典。例子中,命令先比較 c,然后比較 h,然后比較 r,接著比較 1,自然 11會在 2前面了。這里可以添加 -V選項修改。

sort -k1,1V -k2,2n test.bed
chr1    9   28
chr1    10  19
chr1    26  39
chr1    40  50
chr2    35  54
chr3    32  47
chr11    22  56

是不是覺得這樣更可觀一些?不過通常在處理數據時不做此處理,符合規范的數據可以讓后續處理程序效率更高。

用uniq尋找唯一值

cat test.letter
A
A
B
C
B
C
C
C
D
F
D

uniq test.letter
A
B
C
B
C
D
F
D
#只把連續的相同的字符去掉了,`sort`命令可以把相同字符搞到一起
sort test.letter | uniq
A
B
C
D
F
sort test.letter | uniq -c
2 A
2 B
4 C
2 D
1 F
#加 -c選項計數
sort test.letter | uniq -c | sort -rn
4 C
2 D
2 B
2 A
1 F

Join 命令

用來連接文件。 假設現在我們有兩個文件:

cat example.bed
chr1    26  39
chr1    32  47
chr3    11  28
chr1    40  49
chr3    16  27
chr1    9   28
chr2    35  53
cat example_length.txt
chr1    53453
chr2    34356
chr3    24356

我想把第二個文件說明染色體長度添加到第一個文件對應染色體的第三列。 我們首先要給文件排序(使用 join前必須做),然后使用 join命令。

sort -k1,1 example.bed > example_sorted.bed
sort -c -k1,1 example_length.txt
join -1 1 -2 1 example_sorted.bed example_length.txt > example_with_length.txt

cat example_with_length.txt
chr1 26 39 53453
chr1 32 47 53453
chr1 40 49 53453
chr1 9 28 53453
chr2 35 53 34356
chr3 11 28 24356
chr3 16 27 24356

命令基本語法是
join -1 -2

既然名字叫join,就是兩者必須有共同之處,通過共同的支點將兩者連為一體。 -1和 -2選項后接參數分別指定了這個支點,也就是連接的域(列)。比如例子中,都是兩個文件的第一列。

兩個文件中,第一列都共有 chr1(2)(3)。如果第二個文件沒有 chr3, join之后也沒了!!

我們可以通過 -a選項指定哪一個文件可以不遵循配對

join -1 1 -2 1 -a 1 example_sorted.bed example_length_alt.txt
chr1 26 39 53453
chr1 32 47 53453
chr1 40 49 53453
chr1 9 28 53453
chr2 35 53 34356
chr3 11 28
chr3 16 27

awk 可以說是一門語言了

awk是文本處理的一把好手,雖然它不能像 python, R干一些高級復雜的主題工作,但是它具備完整的命令操作和編程體系,手冊參考:http://man.linuxde.net/awk

首先要明白的是,awk按行處理數據。在shell知識里,如果把一個文檔看做一張表。那么一行就是一個記錄,一列就是一個域。可以看出, awk就是按記錄處理文本的。

其次是awk的程序結構是
pattern {action}
pattern可以是表達式或者正則表達式。pattern有點像 if語句,當它滿足時就會執行相應的動作。

另一個 awk核心是它用$0表示所有列,$1$2...等等表示對應的列。我們可以很方便地用它進行操作。

awk '{print $0}' example.bed

chr1    26  39

chr1    32  47

chr3    11  28

chr1    40  49

chr3    16  27

chr1    9   28

chr2    35  53

awk '{print $1}' example.bed

chr1

chr1

chr3

chr1

chr3

chr1

chr2

#print語句就像動作一樣輸出你操作的結果。

awk '{ print $2 "\t" $3}' example.bed

26    39

32    47

11    28

40    49

16    27

9    28

35    53

awk '{ print $2 $3}' example.bed

2639

3247

1128

4049

1627

928

3553

wsx@wsx-ubuntu:/tmp$ awk '{ print $2 , $3}' example.bed

26 39

32 47

11 28

40 49

16 27

9 28

35 53

了解上述幾個語句的不同。

表示染色體名一般用帶 chr或者不帶 chr標志兩種方式。當我們要用到這兩種時,肯定要讓它們能夠對應起來,也就是轉換。 awk命令可以非常方便地添加 chr標記。

下面我先把例子文件的 chr去掉,然后加上試試。

awk '{ print $1}' example.bed

chr1

chr1

chr3

chr1

chr3

chr1

chr2

awk '{ print $1}' example.bed | cut -c 4

1

1

3

1

3

1

2

awk '{ print $1}' example.bed | cut -c4 | awk '{print "chr"$1}'

chr1

chr1

chr3

chr1

chr3

chr1

chr2

awk作為一門編程語言,它支持各種操作符(運算,邏輯,判斷)喔。

awk '$3 - $2 >18' example.bed

chr1    9   28

awk '$1 ~/chr1/ && $3 - $2 > 10' example.bed

chr1    26  39

chr1    32  47

chr1    9   28

這里 ~ 符號用來匹配正則表達式

還有 awk存在一些變量,像NR表示行號, OFS表示輸出分隔符等。

awk 'NR >= 3 && NR <= 5' example.bed

chr3    11  28

chr1    40  49

chr3    16  27

如果我們想把 gtf文件轉換成為 bed格式,可以使用

head -n 1000 Homo_sapiens.GRCh37.75.gtf | awk '!/^#/{ print $1 "\t" $4-1 "\t" $5} ' | head -n 3

1    11868   14412

1    11868   14409

1    11868   12227

用sed進行流編輯

sed工作流:讀取$\to$執行命令$\to$顯示。默認情況,所有的命令都會一個叫做在模式空間(pattern buffer)的緩沖區進行。因此不會改變原始輸入文件的內容。

語法規則
sed即支持在命令行中用單引號輸入執行命令,也支持執行含有sed命令的文件。使用方式如下:
sed [‐n] [‐e] 'command(s)' files
sed [‐n] ‐f script files
選項
sed 后面首先需要跟參數,支持的參數有:
-n:禁止顯示所有輸入內容,只顯示經過sed處理的行(常用)
-e:直接在命令列模式上進行 sed 的動作編輯,接要執行的一個或者多個命令
-f:執行含有sed 動作的文件-rsed 的動作支持的擴展正則(默認基礎正則)
-i :直接修改讀取的文件內容,不輸出。

作用區域
默認情況下,sed命令會作用于文本數據的所有行。如果只想作用于某些行時,則需要使用在命令通過行號或者文本過濾的方式前指明作用區域。

行號
使用數字行號時,類似于R中的向量子集提取。單獨數字表示某一行,逗號分割指示行范圍,另外 m,+n表示從m行開始向下n行, m~n表示從m行開始的每n行。

例如sed ‐n '2~2 p' test.txt輸出偶數行, sed ‐n '1~2 p'test.txt輸出奇數行內容。

文本過濾
'/pattern/ command'可以只在包含pattern 的行中執行命令。如 sed ‐n '/hello/ p' test.txt只會打印出包含hello的行。sed ‐n '/hello/, /world/ p' test.txt 打印兩者之間的所有行。
特殊情況下也可以將文本過濾和行號結合使用,sed ‐n '/hello/,+5 p' test.txt打印第一次出現hello的下面5行

命令

p 復制

復制模式空間中的內容,如果不和 -n參數連用,每一行都會在屏幕輸出兩次,一行正常輸出一行復制,結合 -n 參數后就可以打印需要的內容。

d 刪除

支持按照行號或者匹配來刪除。

i 插入

有的時候一個結果文件沒有essay-header,使用sed 可以輕松完成。在匹配位置之前插入內容。
sed '1i name\tlength\foldchange' test.txt

a 追加

和插入命令的區別在于在匹配位置后一行插入內容,,如果想在末尾插入一行信息時將作為地址。 `sed 'a auther:zhaofei' test.txt`

c 行替換

有了行的刪除插入和追加自然也就會有行替換。

sed '$c auther:zhaofei' test.txt

y 字符轉換

sed中的y命令可以實現一一映射的字符替換(注意和s命令的區別)。

[address]y/inchars/outchars/ 
#inchars中的第一個字符會被轉換為outchars中的第一個字符,第二個字符會被轉換成outchars中的第二個字符,直持續到處理完指定字符。如果inchars和outchars的長度不同會報錯

l 輸出隱藏字符

類似與cat -A,但是顯示隱藏字符形式不同。

w 寫入新文件

增強版的cp,只復制自己想要的東西,也可以將一個文件按不同的篩選條件分開保存。

sed -n -e '/a/ w a.txt' -e '1,10 w b.txt' test.txt
`sed '1,10d;w new.txt' test.txt

r 讀取文件

如果現在a文件的某個地方插入b文件,如在第三行插入

sed '3r b.txt' a.txt

e 執行外部命令

首先要區別于參數-e,這個e是在''里面的命令

sed 'e echo "hello"' test.txt

i 反向執行

在命令前加!反向執行命令

sed '/hello/!d' test.txt
#效果和下面的命令一致
sed -n '/hello/p' test.txt

n 匹配行下移一行操作

提前讀取當前行的下一行內容,并且覆蓋當前模式空間中的行

# 首先匹配到第三行,然后移動到第四行進行刪除
# 所及結果是

1

2

3

5


seq 5 |sed 'n;d' #效果類似與輸出奇數行

seq 5 |sed -n 'n;p' #效果類似與輸出偶數行

= 打印行號

sed '/hello/!d;=' test.txt

s 替換

通用寫法 [address1[,address2]]s/pattern/replacement/[flags]

這里pattern部分支持正則匹配,flags包括n(替換第n個匹配項),g(全局替換),p(輸出改變的行,結合-n),i(忽略大小寫匹配),w(保存改變的行到新文件)。

如果要替換的的內容包括了 /,第一種方式是使用 /進行轉義,第二種方法是使用 @ | ! ^作為分隔符。

有時候我們會對文件中的目錄進行替換,可以下面的寫法

pwd |sed 's@/home/zhaofei@/home/feizhao@'

pwd |sed 's^/home/zhaofei^/home/feizhao^'

pwd |sed 's|/home/zhaofei|/home/feizhao|

pattern支持各種正則表示法,例如

^ 行首

$ 行尾

. 換行符之外的任意單個字符

? 匹配之前項0次或者一次

+ 匹配1次或者多次

* 匹配0次或者多次

{n} 匹配n次

{n,} 匹配至少n次

{m,n} 至少m,最多n

[] 匹配任意一個

[-] 匹配范圍中的一個

[^] 排除字符

| 或者


# posix字符類


[:alnum:] 字母數字

[:alpha:] 字母

[:blank:] 空格制表符

[:digit:] 數字

[:lower:] 小寫字母

[:upper:] 大寫字母

[:punct:] 標點

[:space:] 所有空白符(換行符和回車)


#元字符

\s 單個空白

\w 單詞

在進行匹配替換時,我們有時候并不想刪除匹配的內容,只是希望其以另一種形式和替換內容一起出現。在sed中,特殊字符 &用來存儲匹配模式中的內容。

例如

sed 's/[[:digit:]]/number = &/ test.txt

sed 單行命令 可以完全替代上面所有的命令。

# 刪除空行

sed '/^$/d'

#每行后增加空行

sed G

# 在每5行后增加一空白行

gsed '0~5G'

# 在匹配式樣“regex”的行之后插入一空行

sed '/regex/G'

# 在匹配式樣“regex”的行之前和之后各插入一空行

sed '/regex/{x;p;x;G;}'

# 過濾所有的html標簽

sed 's/<[^>]*>//g ; /^$/d' html.txt

# 代替 cat 功能 

sed ''

# 代替 head 功能 

sed '10 q'

# Dos2unix

sed 's/^M$//'

# Unix2dos

sed 's/$/\r/'

# nl(添加行號)

# sed行號會獨占一行

sed = input.file | sed 'N;s/\n/\t/'


# tee

sed ‐n 'p; w new.txt'

# 代替 grep 功能 

sed ‐n '/pattern/p'

# grep -v

sed ‐n '/pattern/p!'

# 計算行數

sed -n '$='

# 多個內容同時替換

sed 's/a\|b\|c/d/' tmp.txt

# 將每兩行連接成一行

sed '$!N;s/\n/ /'

# 如果當前行以等號開頭,將當前行并到上一行末尾

# 并以單個空格代替原來行頭的“=”

sed -e :a -e '$!N;s/\n=/ /;ta' -e 'P;D'

# 顯示包含“AAA”、“BBB”或“CCC”的行(任意次序)

sed '/AAA/!d; /BBB/!d; /CCC/!d'
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,983評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,772評論 3 422
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,947評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,201評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,960評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,350評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,406評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,549評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,104評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,914評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,089評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,647評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,340評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,753評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,007評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,834評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,106評論 2 375

推薦閱讀更多精彩內容