Форум сайта python.su
0
Добрый день. Изучаю Python ровно 2 часа, гугл не спасает.
Хочу запилить небольшую прогу, которая упростит мне жизнь. Имеется следующий код:
import subprocess import re import os serverRegex = re.compile("server[0-9]+.sh") clientRegex = re.compile("client[0-9]+.sh") currentDir = os.getcwd() remoteDir = "/home/andrey/test" os.chdir(remoteDir) process = subprocess.Popen(["ls"], stdout=subprocess.PIPE) out, err = process.communicate() servers = serverRegex.findall(out) clients = clientRegex.findall(out) os.chdir(currentDir) print ("Current work dir: %s" % currentDir) print ("Remote work dir: %s" % remoteDir) print ("Out: %s" % out) print ("Servers: %s" % servers) print ("Clients: %s" % clients) print ("Amount of servers is: %s" % len(servers)) print ("Amount of clients is: %s" % len(clients))
['server10.sh', 'server1.sh', 'server2.sh', 'server3.sh', 'server4.sh', 'server5.sh', 'server6.sh', 'server7.sh', 'server8.sh', 'server9.sh']
['server1.sh', 'server2.sh', 'server3.sh', 'server4.sh', 'server5.sh', 'server6.sh', 'server7.sh', 'server8.sh', 'server9.sh', 'server10.sh']
Офлайн
0
Нашел ещё один наркоманский способ, но результат примерно такой же
import os import re remoteDir = "/home/andrey/test" files = os.listdir(remoteDir) serverRegex = re.compile("server\d+\.sh") clientRegex = re.compile("client\d+\.sh") servers = serverRegex.findall(''.join(files)) clients = clientRegex.findall(''.join(files)) for server in servers: print ("Got server: %s" % server) for client in clients: print ("Got client: %s" % client)
servers = serverRegex.findall(files)
Офлайн
857
>>> import re >>> >>> def tr(s): ... pat = r'(\d+)\.sh$' ... return int(re.search(pat, s).group(1)) ... >>> lst = ['server10.sh', 'server1.sh', ... 'server2.sh', 'server3.sh', ... 'server4.sh', 'server5.sh', ... 'server6.sh', 'server7.sh', ... 'server8.sh', 'server9.sh'] >>> >>> out = sorted(lst, key=tr) >>> out ['server1.sh', 'server2.sh', 'server3.sh', 'server4.sh', 'server5.sh', 'server6.sh', 'server7.sh', 'server8.sh', 'server9.sh', 'server10.sh'] >>>
Офлайн
253
houeyВо многих случаях если вы разгребаете проблемы, потому что начали думать слишком поздно…
Далее я хочу запускать найденные скрипты в определённом порядке
'server10.sh', 'server1.sh', 'server2.sh'
'server010.sh', 'server001.sh', 'server002.sh'
["server{:03d}.sh".format(i) for i in range(11)] ['server000.sh', 'server001.sh', 'server002.sh', 'server003.sh', 'server004.sh', 'server005.sh', 'server006.sh', 'server007.sh', 'server008.sh', 'server009.sh', 'server010.sh']
Отредактировано doza_and (Май 29, 2017 08:52:53)
Офлайн
186
1) Для просмотра содержания каталога нужно использовать os.listdir.
2) Регулярки работают относительно медленно, по этому ИХМО лучше стараться обойтись без них.
>>> s = "server1.sh" >>> s[6:][:-3] '1' >>> s = "server100.sh" >>> s[6:][:-3] '100'
Офлайн
857
RodegastВпервые такое вижу>>> s = "server100.sh" >>> s[6:][:-3] '100'
>>> 'server1.sh'[6:-3] '1' >>> 'server12345.sh'[6:-3] '12345' >>>
RodegastЗавтра там будет имя в виде serverabc123.sh или abc123.sh и регулярка сработает без каких-либо изменений, потому что поглощает широкое множество строк. Всё, что касается файловых имён, нужно разбирать регулярками, так как бухгалтерша (образно называя так класс пользователей) не будет тебе 001 вводить или даже английский в именах соблюдать, поэтому устройство имени должно классически быть ослаблено (как ослабляют предусловие у подпрограммы), чтобы при любых изменениях в поступающих данных вероятность изменения кода для распознавания этих данных стремилась к нулю.
Регулярки работают относительно медленно
Отредактировано py.user.next (Май 29, 2017 12:18:23)
Офлайн
186
> Впервые такое вижу
Тебя что-то удивляет?
> Завтра там будет имя в виде …
Если это имя будет, то наверно из-за того что пользователь допустил ошибку и ему надо дать по рукам.
> Если там будет comp1.sh, comp2.sh или client1.sh, client2.sh или serv1.sh, serv2.sh, то она без проблем это отсортирует между собой.
А если эти comp1.sh или serv2.sh там случайно оказались, то их тоже запустят? А если там файл PahcBarmina007.sh окажется и запускаться всё это будет под root-ом?
Офлайн
857
RodegastНу, ты говоришь о скорости, а сам применяешь два среза вместо одного. А при каждом срезе ведь создаётся новая строка. Поэтому и показалось странным, что ты такое применил, будто точно не знаешь, как срезы работают.
Тебя что-то удивляет?
RodegastДа бывало такое, сегодня надо скрипт на одной группе файлов применить, а завтра эти файлы приходят с другого компа под другими именами. Устроены одинаково, но префиксы различаются.
Если это имя будет, то наверно из-за того что пользователь допустил ошибку и ему надо дать по рукам.
RodegastДа всякое бывает, но обычно готовится группа файлов (копируется в директорию), да и селектор можно добавить ещё до запуска скрипта (выбрать нужное множество файлов). У тебя же там надо будет не только выбрать, но и переименовать их, потому что из-за фиксированных срезов всё сломается, скрипт будет не применим. А переименуешь файлы, обратно уже их не переименуешь после обработки, потому что старые имена станут неизвестны. Так что придётся тебе всё-таки скрипт менять сам, что является плохим стилем, так как разных ситуаций с именами файлов может быть много.
А если эти comp1.sh или serv2.sh там случайно оказались, то их тоже запустят?
Отредактировано py.user.next (Май 29, 2017 13:04:35)
Офлайн
186
> Ну, ты говоришь о скорости, а сам применяешь два среза вместо одного. А при каждом срезе ведь создаётся новая строка.
Как раз из-за строки я их и применяю. Её создание на скорость почти не влияет, но зато это привносит гибкость. Например если я захочу проверять начало файла на “server”, то достаточно дописать:
s[6:] if s[:6] == "server" else "" [:-3]
Офлайн
0
Ребят, в общем у меня в продолжении темы появился вопрос. Если кто знает С++ - я хочу написать полный аналог данной проги на С++, но уже на Python.
Суть такова:
1. Завожу вектор строк
2. Удаляю ненужные элементы из вектора (при этом передаю вектор по ссылке)
#include <iostream> #include <vector> #include <string> void RemoveSuperfluousItems(const std::string& sPattern, std::vector<std::string>& items) { for (auto it = items.begin(); it != items.end();) if (it->find(sPattern) == std::string::npos) it = items.erase(it); else ++it; } void Print(const std::vector<std::string>& items) { for (const auto& item : items) std::cout << item << std::endl; std::cout << std::endl; } int main(int argc, char* argv[]) { std::vector<std::string> files = { "server1.sh", "server3.sh", "client1.sh", "server2.sh", "1.sh", "2.sh" }; Print(files); RemoveSuperfluousItems("server", files); Print(files); return 0; }
def removeSuperfluousItemsFromList(items, pattern): _items = items[:] for item in _items: if pattern not in item: _items.remove(item) return _items lst = ['1', 'server', '3'] print (lst) lst = removeSuperfluousItemsFromList(lst, 'server') print (lst)
['1', 'server', '3'] ['server']
import re def removeSuperfluousItemsFromList(items, pattern): _items = items[:] print ("Items length is %s" % len(_items)) for item in _items: if pattern in item: continue else: _items.remove(item) print ("Items length is %s" % len(_items)) print (_items) return _items def tr(s): digit_pattern = r'(\d+)\.sh$' result = re.search(digit_pattern, s) if result is None: return 0 return int(result.group(1)) #remoteDir = "/home/andrey/test" #files = os.listdir(remoteDir) files = ['server1.sh', 'client1.sh', 'server2.sh', 'client4.sh', 'client.sh'] # тут хочу сделать копирование по значению (т.е. получить 2 независимых массива) servers = files[:] clients = files[:] servers = removeSuperfluousItemsFromList(servers, 'server') clients = removeSuperfluousItemsFromList(clients, 'client') a = sorted(servers, key=tr) b = sorted(clients, key=tr) test = ['1.sh', '0.sh', 'test5.sh', 'test3.sh'] c = removeSuperfluousItemsFromList(test, 'test') c = sorted(test, key=tr) print (a) print (b) print (c)
Items length is 5 Items length is 3 ['server1.sh', 'server2.sh', 'client.sh'] Items length is 5 Items length is 3 ['client1.sh', 'client4.sh', 'client.sh'] Items length is 4 Items length is 3 ['0.sh', 'test5.sh', 'test3.sh'] ['client.sh', 'server1.sh', 'server2.sh'] ['client.sh', 'client1.sh', 'client4.sh'] ['0.sh', '1.sh', 'test3.sh', 'test5.sh']
Офлайн