2

I am writing a java program from terminal using printf and redirecting its output to a .java file but printf fails to interpret the horizontal backslash tab (\t), and when I have an exclamation mark (!) in the string, it doesn't even print and fails with this error:

bash: !": event not found

  • How do I force printf to include a horizontal tab?

  • And how do I include an exclamation without getting the above error?

commandline argument:

$ printf "%s\n" "public class {" "\tpublic static void main(String[] args) {" "dogBark()" "}" "public static void dogBark() {" "System.out.println("Woof")" "}" "}" > barkingDog.java

output from .java file

$ less barkingDog.java
public class {
\tpublic static void main(String[] args) {
dogBark()
}
public static void dogBark() {
System.out.println(Woof)
}

}

3 Answers 3

7

Using a here-document would probably be cleaner and easier to maintain than using printf. However, from the bash shell's built-in help printf

 %b   expand backslash escape sequences in the corresponding argument

and to prevent bash from treating ! as a history expansion, single-quote your strings:

$ printf '%b\n' 'public class {' '\tpublic static void main(String[] args) {' 'dogBark()' '}' 'public static void dogBark() {' 'System.out.println("Woof!")' '}' '}'
public class {
    public static void main(String[] args) {
dogBark()
}
public static void dogBark() {
System.out.println("Woof!")
}
}

See How to echo a bang!

5
  • @Jesse yes it does work. I didn't see that he replaced the s variable with a b.
    – bit
    Jul 7, 2018 at 20:33
  • I'm using single quotes around Woof! and double for everything else but the error still persists. Does it have to be the other way around?
    – bit
    Jul 7, 2018 at 20:39
  • 1
    @MyWrathAcademia: The string 'Woof!' is wrapped within double quotes, which will escape the single quotes. So yes, try the other way around.
    – jesse_b
    Jul 7, 2018 at 20:42
  • @steeldriver why is it that changing the s after % to a b caused printf to start interpreting the horizontal tab \t when previously it wasn't?
    – bit
    Jul 9, 2018 at 20:33
  • @MyWrathAcademia because that's what it's designed to do - format the argument as a backslash escaped string instead of a regular string Jul 9, 2018 at 20:44
3

printf can not interpret backslash characters (like \t) in the string printed. Only in the format string:

$ printf '\t%s' "test" "string"
    test    string

As a workaround you can insert a real tab in the string to print.

It is possible to use a format string of %b which could interpret backslash characters:

$ printf '%b' "\ttest" "\tstring"
    test    string

The character ! is used for history expansion. But that happens only when used unquoted. Just quoting it (with \ or ' not ") should prevent expansion. If that is still a problem, history expansion could be disabled:

$ set +H

This should work:

$ printf "%b\n" \
         "public class {" \
         "\tpublic static void main(String[] args) {" \
         "dogBark()" \
         "}" \
         "public static void dogBark() {" \
         "System.out.println(\"Woof\!\")" \
         "}" \
         "}" > barkingDog.java

$ cat barkingDog.java 
public class {
        public static void main(String[] args) {
dogBark()
}
public static void dogBark() {
System.out.println("Woof!")
}
}

But clearly, a here document is simpler:

$ cat <<\EOT >barkingDog.java
public class {
       public static void main(String[] args) {
dogBark()
}
public static void dogBark() {
System.out.println("Woof!")
}
}
EOT
4
0

I think you can accomplish what you want using ANSI-C quoting like so:

printf "%s\n" "public class {" \
$'\tpublic static void main(String[] args) {' \
"dogBark()" \
"}" \
"public static void dogBark() {" \
"System.out.println("Woof")" \
"}" \
"}" > barkingDog.java

Output:

public class {
        public static void main(String[] args) {
dogBark()
}
public static void dogBark() {
System.out.println(Woof)
}
}

As for the exclamation mark, when history expansion is enabled bash will attempt to expand ! when inside double quotes. So single quote it or escape it with \.

7
  • I tried changing the quotes that wrap the string containing \t to single and it didn't work
    – bit
    Jul 7, 2018 at 20:23
  • now it works. Why did the dollar sign ($) fix it?
    – bit
    Jul 7, 2018 at 20:27
  • 3.1.2.4 ANSI-C Quoting
    – jesse_b
    Jul 7, 2018 at 20:28
  • thanks for the link, changing from double to single still gives the same error though.
    – bit
    Jul 7, 2018 at 20:35
  • For the exclamation mark? Can you update your question with an example that includes the exclamation mark?
    – jesse_b
    Jul 7, 2018 at 20:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .