-5

I have the following file:

$ cat files
foo.txt
bar.js

I am looking to use bash awk to only print files not ending with .js.

This works fine when using single quoted awk:

$ awk '$1 !~ /.js$/ {print $1}' files
foo.txt

However, when using double quoted awk:

$ awk "\$1 !~ /.js$/ {print \$1}" files
-bash: !~: event not found
Foo
  • 232
  • 2
    Why dou want to use double quotes in awk ? – Gilles Quénot Mar 28 '23 at 11:20
  • 1
    The environment in which awk is running demands it – Foo Mar 28 '23 at 11:20
  • Explain us which env. Windows? – Gilles Quénot Mar 28 '23 at 11:21
  • 1
    Is the history expansion actually a problem in that environment, or just in your interactive shell? – muru Mar 28 '23 at 11:22
  • If you use windows, don't use cmd.exe, but PowerShell that allow single quoting – Gilles Quénot Mar 28 '23 at 11:23
  • @GillesQuénot I am using bash in WSL. – Foo Mar 28 '23 at 11:23
  • @muru what do you mean? – Foo Mar 28 '23 at 11:23
  • If you re in a Linux OS in WSL, use single quotes. If you want to pass variables: awk -v foo=bar 'BEGIN{print foo}' – Gilles Quénot Mar 28 '23 at 11:24
  • 2
    Why must you use awk? It would be easier to use grep -v '\.js$' – Chris Davies Mar 28 '23 at 11:24
  • @roaima who said I must use awk? I am curious on how I can get this working – Foo Mar 28 '23 at 11:26
  • 1
    There's no reason at all to use double quotes in awk in Linux – Gilles Quénot Mar 28 '23 at 11:28
  • 1
    awk and single quotes work perfectly fine for me in WSL. – muru Mar 28 '23 at 11:52
  • @muru I am asking about how to do it with double quotes – Foo Mar 28 '23 at 11:53
  • 4
    No, you're asking how to pound in a nail with a glass bottle. See also: https://meta.stackexchange.com/q/8891/270345. The correct answer is: "*Don't do it.*" – muru Mar 28 '23 at 11:56
  • 2
    Using single quotes would be easier also in that you wouldn't need to escape $ signs, or other double quotes inside the awk script (if you have string constants there). Disabling history expansion would fix the issue with !. But if you can't do that either, for whatever reason, you could also rewrite the awk exprassion as ! ($1 ~ /.../) as !<space> doesn't trigger history expansion. – ilkkachu Mar 28 '23 at 11:57
  • 1
  • @muru can you explain what the downsides are, aside from readability? – Foo Mar 28 '23 at 11:59
  • 4
    You already know the downsides - your script is being interpreted by the shell before awk sees it and so you have the problem you're asking about with ! and you've had to escape $s. So we're left with what appears to be an XY Problem as you appear to be asking how to implement something you should never do rather than asking about how to do whatever it is you want to do and so it got downvoted and closed. – Ed Morton Mar 28 '23 at 13:20
  • @Foo If you were interested in why you got this error, you got your answer and can ignore the awk warriors. If you are interested in how to improve your awk coding, I suggest to ask a new question for this. Anyhow, stay happy and move on. – Philippos Mar 28 '23 at 13:28
  • @Philippos It has certainly been a good reminder as to how toxic this place can be – Foo Mar 28 '23 at 13:29
  • 1
    @Foo If you have specific issues you want to discuss publicly, please open an issue on our Meta site and explain what you believe is toxic. We don't want this site to be toxic, so anything we can do to improve it would be nice to know. The Meta site for U&L is available here: https://unix.meta.stackexchange.com/ – Kusalananda Mar 28 '23 at 13:32
  • 2
    @Foo If you want to complain privately about me and how I do moderation, then don't hesitate to contact StackExchange using the contact link at the bottom of any page. The moderator actions I have taken with regards to this particular question have been: 1) closed the question as a 3rd "voter", 2) cleaned up comments. – Kusalananda Mar 28 '23 at 13:36

2 Answers2

1

Don't do that.

With a simple variable argument in :

$ awk -v exclude='\.js$' '$1 !~ exclude' file
foo.txt

Or, import the pattern via the environment (handy way to support patterns containing \\):

$ exclude='\.js$' awk '$1 !~ ENVIRON["exclude"]' file

As mentioned in comments (now deleted):

$ awk "\$1 !""~ /.js$/ {print \$1}" file

may work, but it's not the recommended way. This is just plain ugly. Learn how to use the proper way.

-1

You are one of millions to be fooled by history expansion, which is active by default, even if only one of a thousand users ever use it.

The best is to disable it in your shell startup file by using set +H or set +o histexpand. Then you can use ! without weird problems.

Philippos
  • 13,453
  • Comments have been moved to chat; please do not continue the discussion here. Before posting a comment below this one, please review the purposes of comments. Comments that do not request clarification or suggest improvements usually belong as an answer, on [meta], or in [chat]. Comments continuing discussion may be removed. – Kusalananda Mar 28 '23 at 13:23