Уведомления

Группа в Telegram: @pythonsu

#1 Май 29, 2017 00:04:07

houey
Зарегистрирован: 2017-05-28
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

Сортировка строк

Добрый день. Изучаю 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))

Вроде работает всё как и ожидается.
Вот вывод программы:

Servers:
Clients:
Amount of servers is: 10
Amount of clients is: 10


Далее я хочу запускать найденные скрипты в определённом порядке (в зависимости от числа в конце файла), т.е. server1, server2, ….

Подскажите как это можно сделать именно средствами Python, желательно без костылей.
Прекрасно знаю что можно написать более коротко и т.п., либо юзать ls с grep'ом, но сейчас стоит задача изучить Python на минимальном уровне, поэтому собственно такой вопрос.

В итоге хочу чтобы массив:
 ['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']

Спасибо!

Офлайн

#2 Май 29, 2017 00:25:12

houey
Зарегистрирован: 2017-05-28
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

Сортировка строк

Нашел ещё один наркоманский способ, но результат примерно такой же

 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)

Не подскажите случайно как можно применить regex к списку? И получить результат?
Т.е. по сути хочу сделать:

 servers = serverRegex.findall(files)

Офлайн

#3 Май 29, 2017 03:34:18

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10014
Репутация: +  857  -
Профиль   Отправить e-mail  

Сортировка строк

  
>>> 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']
>>>



Офлайн

#4 Май 29, 2017 08:49:27

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Сортировка строк

houey
Далее я хочу запускать найденные скрипты в определённом порядке
Во многих случаях если вы разгребаете проблемы, потому что начали думать слишком поздно…

Если бы вы назвали файлы не
 'server10.sh', 'server1.sh', 'server2.sh'
а
 'server010.sh', 'server001.sh', 'server002.sh'
то данного вопроса не было, причем не только в питоне но и в bash grep и куче других программных средств, поскольку в этом случае нумерация совпадает с алфавитным порядком. Имена тогда можно генерировать а не получать из директории с последующей фильтрацией и парсингом имен, что конечно гораздо быстрее и гораздо проще программируется (важно для большого количества файлов).
 ["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)

Офлайн

#5 Май 29, 2017 11:05:46

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2842
Репутация: +  186  -
Профиль   Отправить e-mail  

Сортировка строк

1) Для просмотра содержания каталога нужно использовать os.listdir.
2) Регулярки работают относительно медленно, по этому ИХМО лучше стараться обойтись без них.

 >>> s = "server1.sh"
>>> s[6:][:-3]
'1'
>>> s = "server100.sh"
>>> s[6:][:-3]
'100'
3) Использовать os.chdir не нужно.



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#6 Май 29, 2017 12:10:53

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10014
Репутация: +  857  -
Профиль   Отправить e-mail  

Сортировка строк

Rodegast
  
>>> s = "server100.sh"
>>> s[6:][:-3]
'100'
Впервые такое вижу
  
>>> 'server1.sh'[6:-3]
'1'
>>> 'server12345.sh'[6:-3]
'12345'
>>>

Rodegast
Регулярки работают относительно медленно
Завтра там будет имя в виде serverabc123.sh или abc123.sh и регулярка сработает без каких-либо изменений, потому что поглощает широкое множество строк. Всё, что касается файловых имён, нужно разбирать регулярками, так как бухгалтерша (образно называя так класс пользователей) не будет тебе 001 вводить или даже английский в именах соблюдать, поэтому устройство имени должно классически быть ослаблено (как ослабляют предусловие у подпрограммы), чтобы при любых изменениях в поступающих данных вероятность изменения кода для распознавания этих данных стремилась к нулю.
Короче, ты фиксируешься на том, что там обязательно должно быть слово server, а зачем тебе на этом фиксироваться? Наоборот, надо убрать это условие, чтобы программа стала больше имён принимать для сортировки. Если там будет comp1.sh, comp2.sh или client1.sh, client2.sh или serv1.sh, serv2.sh, то она без проблем это отсортирует между собой.



Отредактировано py.user.next (Май 29, 2017 12:18:23)

Офлайн

#7 Май 29, 2017 12:49:24

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2842
Репутация: +  186  -
Профиль   Отправить e-mail  

Сортировка строк

> Впервые такое вижу

Тебя что-то удивляет?

> Завтра там будет имя в виде …

Если это имя будет, то наверно из-за того что пользователь допустил ошибку и ему надо дать по рукам.

> Если там будет comp1.sh, comp2.sh или client1.sh, client2.sh или serv1.sh, serv2.sh, то она без проблем это отсортирует между собой.

А если эти comp1.sh или serv2.sh там случайно оказались, то их тоже запустят? А если там файл PahcBarmina007.sh окажется и запускаться всё это будет под root-ом?



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#8 Май 29, 2017 13:00:19

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10014
Репутация: +  857  -
Профиль   Отправить e-mail  

Сортировка строк

Rodegast
Тебя что-то удивляет?
Ну, ты говоришь о скорости, а сам применяешь два среза вместо одного. А при каждом срезе ведь создаётся новая строка. Поэтому и показалось странным, что ты такое применил, будто точно не знаешь, как срезы работают.

Rodegast
Если это имя будет, то наверно из-за того что пользователь допустил ошибку и ему надо дать по рукам.
Да бывало такое, сегодня надо скрипт на одной группе файлов применить, а завтра эти файлы приходят с другого компа под другими именами. Устроены одинаково, но префиксы различаются.

Rodegast
А если эти comp1.sh или serv2.sh там случайно оказались, то их тоже запустят?
Да всякое бывает, но обычно готовится группа файлов (копируется в директорию), да и селектор можно добавить ещё до запуска скрипта (выбрать нужное множество файлов). У тебя же там надо будет не только выбрать, но и переименовать их, потому что из-за фиксированных срезов всё сломается, скрипт будет не применим. А переименуешь файлы, обратно уже их не переименуешь после обработки, потому что старые имена станут неизвестны. Так что придётся тебе всё-таки скрипт менять сам, что является плохим стилем, так как разных ситуаций с именами файлов может быть много.



Отредактировано py.user.next (Май 29, 2017 13:04:35)

Офлайн

#9 Май 29, 2017 14:41:11

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2842
Репутация: +  186  -
Профиль   Отправить e-mail  

Сортировка строк

> Ну, ты говоришь о скорости, а сам применяешь два среза вместо одного. А при каждом срезе ведь создаётся новая строка.

Как раз из-за строки я их и применяю. Её создание на скорость почти не влияет, но зато это привносит гибкость. Например если я захочу проверять начало файла на “server”, то достаточно дописать:

 s[6:] if s[:6] == "server" else "" [:-3]
А в случае одного среза эта возможность становится не очевидной.

> потому что из-за фиксированных срезов всё сломается, скрипт будет не применим.

И это хорошо. Ведь никто не знает что в некорректных файлах находится, а если там всё тот же пресловутый патч Бармина.



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#10 Май 29, 2017 23:24:22

houey
Зарегистрирован: 2017-05-28
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

Сортировка строк

Ребят, в общем у меня в продолжении темы появился вопрос. Если кто знает С++ - я хочу написать полный аналог данной проги на С++, но уже на 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;
}

Вывод программы:
server1.sh
server3.sh
client1.sh
server2.sh
1.sh
2.sh

server1.sh
server3.sh
server2.sh

Работает вродё всё как ожидается.

Теперь пытаюсь провернуть подобное на Python'e

 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']

Но вот когда уже хочу скопировать список всех файлов в 2 массива (по сути хочу произвести копирование по значению и всё)

А вот пытаюсь заюзать подобную функцию в проге, которая фигурировала выше:
 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']

как я понял проблема в присваивании, подскажите пожалуйста как пофиксить?
Т.е. по сути мне нужно реализовать функцию, которая будет производить манипуляции именно с тем объектом, для которого был вызван тот или иной метод

Спасибо!

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version