Beside the cosmetic/preference arguments, one reason could be that there are more implementations where [ ! "$a" = "$b" ] fails in corner cases than with [ "$a" != "$b" ].
Both cases should be safe if implementations follow the POSIX algorithm, but even today (early 2018 as of writing), there are still implementations that fail. For instance, with a='(' b=')':
$ (a='(' b=')'; busybox test "$a" != "$b"; echo "$?")
0
$ (a='(' b=')'; busybox test ! "$a" = "$b"; echo "$?")
1
With dash versions prior to 0.5.9, like the 0.5.8 found as sh on Ubuntu 16.04 for instance:
$ a='(' b=')' dash -c '[ "$a" != "$b" ]; echo "$?"'
0
$ a='(' b=')' dash -c '[ ! "$a" = "$b" ]; echo "$?"'
1
(fixed in 0.5.9, see https://www.mail-archive.com/dash@vger.kernel.org/msg00911.html)
Those implementations treat [ ! "(" = ")" ] as [ ! "(" "text" ")" ] that is [ ! "text" ] (test whether "text" is the null string) while POSIX mandates it to be [ ! "x" = "y" ] (test "x" and "y" for equality). Those implementations fail because they perform the wrong test in that case.
Note that there's yet another form:
! [ "$a" = "$b" ]
That one requires a POSIX shell (won't work with the old Bourne shell).
Note that several implementations have had problems with [ "$a" = "$b" ] (and [ "$a" != "$b" ]) as well and still do like the [ builtin of /bin/sh on Solaris 10 (a Bourne shell, the POSIX shell being in /usr/xpg4/bin/sh). That's why you see things like:
[ "x$a" != "x$b" ]
In scripts trying to be portable to old systems.
!(x==y)from(!x)==y. – jimmij Jan 12 '18 at 16:23if [ ! "$string" = "one" ]translates to if not the value of$stringequalsone. And thisif [ "$string" != "one"]translates to if the value of$stringdoes not equal withone? – Jimmy_A Jan 12 '18 at 16:33!=syntax) is just more obvious. – jimmij Jan 12 '18 at 16:48