In regexes, * means "any number of the previous item", not "any number of any characters", like it does in shell patterns. And . means "any single character".
So, to look for "anything, followed by literal .txt", you'd use .*\.txt. Or just \.txt, since usually regex matches search for the match anywhere in the line. Then again \.txt would also match a filename like foo.txtgz, as the .txt would not have to be at the end. You'd need \.txt$ to lock the pattern to the end of line.
The regex *.txt is either meaningless, an error, or looks for a literal asterisk, depending on the implementation and if you're using basic regexes (grep), or extended regexes (grep -E). Best not to use it.
On the other hand, s*.txt would look for "any number of letters s, then any single character, then literal txt". That's a more valid regex, but... still doesn't match sample.txt.
Instead, what happens in your second command, is that because s*.txt is not quoted, the shell expands the s*.txt before grep sees it. If the only matching file is sample.txt, then grep goes looking for that in the output of ls. (If there were multiple matching filenames, the first would be taken as the pattern, and the rest as filenames for grep to read. In that case, it'd ignore the input from the pipe.)
But, ls can take a list of files too, so while you could use
ls | grep '\.txt'
to get any .txt file, it'd probably be easier to just use
ls *.txt
instead.
*), but they have different syntax and meanings. – Gordon Davisson Aug 14 '20 at 21:50grepis for doingg/re/p(i.e looking for a string that matches a regexp and printing the result) within files whilefindis forfinding files (i.e. looking for files who match a given criteria including their name matching a globbing pattern). Btw - don't try to parse the output ofls, see https://mywiki.wooledge.org/ParsingLs. – Ed Morton Aug 15 '20 at 03:47