O padrão que você deseja é algo como ( veja em rubular.com ):
^[a-zA-Z0-9_.-]*$
Explicação:
^ é o começo da âncora de linha
$ é a âncora do fim da linha
[...] é uma definição de classe de personagem
* é a repetição "zero ou mais"
Observe que o traço literal -é o último caractere na definição da classe de caracteres, caso contrário, tem um significado diferente (ou seja, intervalo). O .também tem um significado diferente fora das definições de classe de caractere, mas por dentro, é apenas um literal.
Referências
Em PHP
Aqui está um snippet para mostrar como você pode usar este padrão:
<?php
$arr = array(
'screen123.css',
'screen-new-file.css',
'screen_new.js',
'screen new file.css'
);
foreach ($arr as $s) {
if (preg_match('/^[\w.-]*$/', $s)) {
print "$s is a match\n";
} else {
print "$s is NO match!!!\n";
};
}
?>
As impressões acima ( conforme visto em ideone.com ):
screen123.css is a match
screen-new-file.css is a match
screen_new.js is a match
screen new file.css is NO match!!!
Observe que o padrão é ligeiramente diferente, usando em seu \wlugar. Esta é a classe de caractere para "caractere de palavra".
Referências API
Nota na especificação
Isso parece seguir sua especificação, mas observe que corresponderá a itens como .....etc., que podem ou não ser o que você deseja. Se você puder ser mais específico sobre qual padrão deseja corresponder, a regex será um pouco mais complicada.
O regex acima também corresponde à string vazia. Se você precisar de pelo menos um caractere, use +(um ou mais) em vez de *(zero ou mais) para a repetição.
Em qualquer caso, você pode esclarecer ainda mais sua especificação (sempre ajuda ao fazer perguntas sobre regex), mas espero que você também possa aprender como escrever o padrão com as informações acima.