[英]Match file names and replace with new name
我有兩個帶有相似ID標簽的.txt文件。 我需要做的是從一個文件中獲取ID標記,在另一個文件中進行匹配,然后將ID替換為第一個文件中的名稱。 我需要為1000多個標簽完成此操作。 關鍵是要完全匹配第一個文件中ID標記名稱的一部分並替換它。
每行有一個唯一的ID標記,並且兩個文件之間始終完全匹配(對於位置[6-16] =“ 10737.G1C22”); 匹配分散,因此File1.txt中的第1行可能與File2.txt中的第504行匹配
兩個文件中行的順序無法排序,必須保持
例如:
File1.txt =
TYPE1_10737.G1C22 ---------
...
File2.txt =
10737.G1C22 ----------
我需要File1.txt中的名稱,特別是“ 10737.G1C22”,以便在File2.txt中找到其完全匹配的內容並將其替換為“ TYPE1_10737.G1C22”。
然后,編輯看起來像這樣,現在File2.txt中的名稱根據File1.txt中的匹配項進行了更改:
File2.txt =
TYPE1_10737.G1C22 ---------
...
我嘗試了一些sed函數,但遇到了麻煩。 重要的是,一旦找到完全匹配的名稱,就只能更改名稱的前6個字符,而不能更改其他任何內容。 有超過1000個以上的ID標簽需要匹配和更改。
我正在考慮告訴它精確匹配位置[6-16]並將其替換為File1.txt中的[0-16]的代碼。
任何幫助深表感謝。 這有可能嗎? 我也歡迎其他建議。 謝謝。
ed
解決方案 步驟1.創建File1.txt
和File2.txt
或多或少的樣子你進行實驗,並有一些樂趣(1000線)。 使用此腳本(在臨時目錄中):
#!/bin/bash declare -A table while ((${#table[@]}!=1000)); do key=$(mktemp -u XXXXXXXXXX) key=${key:0:5}.${key:5} table[${key^^}]=1 done { for key in "${!table[@]}"; do echo "TYPE1_$key some junk here" >&3 echo "$key some more junk here" done | shuf > File2.txt } 3> File1.txt
第2步。使用ed
(標准編輯器)進行替換,該腳本包裝在該腳本中:
#!/bin/bash ed -s File2.txt < <( while read l _; do p=${l:6} p=${p//./\\\\.} echo "%s/^$p/$l/" done < File1.txt echo wq )
假設您只有字母數字字符,下划線_
和句點.
。 如果您還有其他字符,請適當修改(以免與正則表達式沖突)。
步驟3.檢查並享受:
vimdiff <(sort File1.txt) <(sort File2.txt)
完成。
注意。 由於ed
是一位真正的編輯,所以替換工作已經就位。 File2.txt
確實已編輯 。
嘿,等等,我可能忽略了16個字符的要求...我習慣了這樣的事實,即您的模式后面有一個空格。 如果在這一點上我的解決方案不好,請告訴我,我將對其進行適當的修改。
但是,請注意,基於Python的解決方案很簡單,因為它不能就地完成,您必須將結果存儲到某個新位置,例如tempfile 。
如果您的文件不是過大,即可以在內存中構造映射,則它很簡單(假設1)名稱與帶下划線的id分開,2)id與帶空格的文本分開,如示例3)這行同時包含ID和名稱4)file1)中每個ID僅存在一個名稱:
file1 = ('TYPE1_10737.G1C22 ---------', )
file2 = ('10737.G1C22 +++++++++++', )
id_name_gen = (l.split(' ', 1)[0] for l in file1)
id2name_mapping = {line.split('_', 1)[1]: line for line in id_name_gen}
有了映射后,替換即可輕松完成(如果找不到匹配項,則保持字符串不變):
id_rest_gen = (l.split(' ', 1) for l in file2)
file2updated_gen = ('{} {}'.format(id2name_mapping.get(id, id), rest) for id, rest in file2)
>>> list(file2updated_gen)
['TYPE1_10737.G1C22 +++++++++++']
您只需要將生成的結果存儲到文件中即可。
python中的一個簡單解決方案:
from collections import OrderedDict
LINES_PER_CYCLE = 1000
with open('output.txt', 'wb') as output, open('test_2.txt', 'rb') as fin:
fin_line = ''
# Loop until fin reaches EOF.
while True:
cache = OrderedDict()
# Fill the cache with up to LINES_PER_CYCLE entries.
for _ in xrange(LINES_PER_CYCLE):
fin_line = fin.readline()
if not fin_line:
break
key, rest = fin_line.strip().split(' ', 1)
cache[key] = ['', rest]
# Loop over the file_1.txt to find tags with given id.
with open('test_1.txt', 'rb') as fout:
for line in fout:
tag, _ = line.split(' ', 1)
_, idx = tag.rsplit('_', 1)
if idx in cache:
cache[idx][0] = tag
# Write matched lines to the output file, in the same order
# as the lines were inserted into the cache.
for _, (tag, rest) in cache.iteritems():
output.write('{} {}\n'.format(tag, rest))
# If fin has reached EOF, break.
if not fin_line:
break
它的作用是讀取高達LINES_PER_CYCLE
從條目file_2.txt
,找到匹配條目file_1.txt
並寫入到輸出。 由於有限的內存(用於高速緩存),將file_1.txt
搜索file_1.txt
。
這假定該標簽/ ID部分是由空格從分離-------
,並且標簽和ID是由一個下划線從自己,即分離。 'tag_idx等等等等'。
我將第一個文件加載到字典中,然后處理第二個文件以匹配鍵,將所有更改輸出到第三個文件:
import re
# Pattern to match in File1
pattern1 = "(\w+)_(\d+\.\w+)\s+.*$"
# Pattern to match in File2
pattern2 = "(\d+\.\w+)\s+.*$"
# Load the 'master' file into a dict,
# with the number as key and 'type' as value.
file1_dict = dict()
with open("File1.txt", "r") as f:
for line in f.readlines():
m = re.match(pattern1, line)
if m:
file1_dict[m.group(2)] = m.group(1)
# Open a new output file to replace File2.txt
with open("File3.txt", "w") as fnew:
# As you process each line in File2.txt,
# find matching entry in above File1 list.
# Either write the old unmatched value or new
# matching, changed value to File3.txt
with open("File2.txt", "r") as f:
for line in f.readlines():
is_found = False
m = re.match(pattern2, line)
if m:
if m.group(1) in file1_dict:
is_found = True
fnew.write("{0}_{1}".format(file1_dict[m.group(1)], line))
if not is_found:
fnew.write(line)
# Then just overwrite File2.txt with new File3.txt contents.
# Original File1.txt
TYPE1_10737.G1C22 ---------
TYPE1_10738.G1C22 ---------
TYPE1_10739.G1C22 ---------
TYPE1_10740.G1C22 ---------
TYPE1_10741.G1C22 ---------
TYPE1_10742.G1C22 ---------
TYPE1_10799.G1C22 ---------
# Original File2.txt
10737.G1C22 ---------
10738.G1C22 ---------
10739.G1C22 ---------
10740.G1C22 ---------
10788.G1C22 ---------
10741.G1C22 ---------
10742.G1C22 ---------
# Results of new File3.txt
TYPE1_10737.G1C22 ---------
TYPE1_10738.G1C22 ---------
TYPE1_10739.G1C22 ---------
TYPE1_10740.G1C22 ---------
10788.G1C22 ---------
TYPE1_10741.G1C22 ---------
TYPE1_10742.G1C22 ---------
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.