Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. Lua Dictionary
  3. String Basics (.. / #)

String Basics (.. / #)

In Lua, strings are immutable values. There are three kinds of string literals: single-quoted, double-quoted, and long strings ([[]]). Strings are concatenated with the .. operator, and their byte length is obtained with the # operator.

Syntax

-- -----------------------------------------------
-- String literal forms
-- -----------------------------------------------
local s1 = "Double-quoted string"
local s2 = 'Single-quoted string'   -- identical behavior to double-quoted
local s3 = [[
Long string
Multiple lines can be written as-is
]]                                   -- [[ ]] for multi-line literals

-- -----------------------------------------------
-- String concatenation (.. operator)
-- -----------------------------------------------
local result = "Terry" .. " " .. "Bogard"  -- .. joins strings

-- -----------------------------------------------
-- String length (# operator)
-- -----------------------------------------------
local len = #result    -- returns byte count (not character count for multibyte text)

-- -----------------------------------------------
-- Escape sequences
-- -----------------------------------------------
local esc = "newline\n\ttab\t backslash\\"  -- \n newline, \t tab, \\ backslash

Syntax Reference

Operator / NotationDescription
"..." / '...'String literals. Double-quoted and single-quoted forms are interchangeable.
[[...]]Long string literal. Allows multi-line text containing newlines without escape sequences.
.. (two dots)String concatenation operator. Returns a new string that is the concatenation of both operands.
# (hash)String length operator. Returns the byte count of the string. For multibyte UTF-8 characters, byte count and character count differ.
\nEscape sequence: line feed (newline).
\tEscape sequence: horizontal tab.
\\Escape sequence: a single backslash character.
\" / \'Escape sequence: embeds a double or single quote inside a string literal.
\NNN (decimal)Escape sequence: the character whose byte value equals the decimal number (e.g. \65A).

Sample Code

kof_string_basic.lua
-- kof_string_basic.lua — string basics sample
-- Uses KOF (The King of Fighters) characters to demonstrate
-- literals, concatenation (..), length (#), and escape sequences

-- -----------------------------------------------
-- Three kinds of string literals
-- -----------------------------------------------

-- Double-quoted literal
local name1 = "Terry Bogard"

-- Single-quoted literal (identical to double-quoted)
local name2 = 'Andy Bogard'

-- Long string literal ([[ ]] for multi-line, no escaping needed)
local profile = [[
Name: Mai Shiranui
Team: Fatal Fury Team
Special move: Ryuenbu
]]

print("=== String Literals ===")
print(name1)
print(name2)
print(profile)

-- -----------------------------------------------
-- String concatenation with .. operator
-- -----------------------------------------------

print("=== Concatenation (.. operator) ===")

-- Multiple strings joined with ..
local fighter = "Joe " .. "Higashi"
print(fighter)

-- Numbers are automatically converted to strings when used with ..
local power = 92
local info = "Ralf Jones power level: " .. power
print(info)

-- Building a longer string with local variables improves readability
local team   = "Fatal Fury Team"
local member = name1 .. ", " .. name2 .. ", Mai Shiranui"
local line   = "[" .. team .. "] " .. member
print(line)
print("")

-- -----------------------------------------------
-- String length (byte count) with # operator
-- -----------------------------------------------

print("=== String Length (# operator) ===")

local ascii_name = "Terry Bogard"
print(ascii_name .. " byte count: " .. #ascii_name)   -- ASCII: 1 char = 1 byte

-- Japanese (UTF-8): 1 character = 3 bytes, so byte count != character count
local jp_name = "テリー・ボガード"
print(jp_name .. " byte count: " .. #jp_name)         -- 8 chars x 3 bytes = 24

-- Empty string has length 0
local empty = ""
print("Empty string byte count: " .. #empty)
print("")

-- -----------------------------------------------
-- Escape sequences
-- -----------------------------------------------

print("=== Escape Sequences ===")

-- \n inserts a newline, \t inserts a tab
local escape_demo = "Special moves:\n\tPower Geyser\n\tTriangle Geyser\n\tPower Dunk"
print(escape_demo)
print("")

-- \\ outputs a literal backslash
local path = "C:\\KOF\\fighters\\terry.lua"
print("File path: " .. path)
print("")

-- \" embeds a double quote inside a double-quoted string
local quote = 'Terry\'s line: "OK, let\'s go!"'
print(quote)
print("")

-- \65 specifies a character by its decimal byte value (65 = 'A')
local byte_demo = "\84\101\114\114\121"   -- T=84, e=101, r=114, r=114, y=121
print("String from byte values: " .. byte_demo)
lua kof_string_basic.lua
=== String Literals ===
Terry Bogard
Andy Bogard

Name: Mai Shiranui
Team: Fatal Fury Team
Special move: Ryuenbu

=== Concatenation (.. operator) ===
Joe Higashi
Ralf Jones power level: 92
[Fatal Fury Team] Terry Bogard, Andy Bogard, Mai Shiranui

=== String Length (# operator) ===
Terry Bogard byte count: 12
テリー・ボガード byte count: 24
Empty string byte count: 0

=== Escape Sequences ===
Special moves:
	Power Geyser
	Triangle Geyser
	Power Dunk

File path: C:\KOF\fighters\terry.lua

Terry's line: "OK, let's go!"

String from byte values: Terry

Common Mistakes

Concatenating a numeric literal directly with .. causes an error

Placing .. immediately after a numeric literal without a space causes Lua to interpret it as ... (varargs), resulting in a syntax error. Always put a space between the number and .., or use tostring() to convert explicitly.

-- NG: no space between a numeric literal and .. causes a syntax error
-- print(42 .." item")
-- OK: add a space or use tostring()
print(42 .. " item")              -- space between number and ..
print(tostring(42) .. " item")    -- explicit conversion with tostring()

The # operator returns byte count, not character count, for multibyte strings

The # operator returns the byte count of a string. For ASCII text, byte count equals character count, but UTF-8 Japanese characters are 3 bytes each, so the result differs from the character count. Use utf8.len() (Lua 5.3 and later) to count characters.

-- NG: # returns byte count, not character count, for Japanese text
local name = "Yagami Iori"    -- ASCII: byte count equals character count
local jpname = "八神庵"
print(#jpname)                 -- 9 (3 chars x 3 bytes; not the character count)
-- OK: use utf8.len() to get the character (code point) count (Lua 5.3+)
local jpname = "八神庵"
print(utf8.len(jpname))        -- 3 (character count)
print(#jpname)                 -- 9 (byte count)

Using == for string comparison (this is correct in Lua)

Developers coming from C often look for a strcmp() equivalent. In Lua, == compares string content directly. There is no strcmp function, and none is needed.

-- NG: strcmp does not exist in Lua
-- if strcmp(name, "Yagami Iori") == 0 then ...
-- OK: use == to compare string contents
local name = "Yagami Iori"
if name == "Yagami Iori" then
    print("match")
end

Overview

Lua strings are immutable values expressed with three kinds of literals: double-quoted, single-quoted, and long strings ([[]]). The .. (two dots) operator concatenates the left and right operands and returns a new string. When a number is used with .., it is automatically converted to a string. The # operator returns the byte count of a string. For ASCII text, byte count matches character count, but UTF-8 Japanese characters are typically 3 bytes each, so # returns byte count, not character count. To handle character counts accurately, use utf8.len() (Lua 5.3 and later), described in the string methods page. Escape sequences include \n (newline), \t (tab), \\ (backslash), and \NNN (decimal byte value).

If you find any errors or copyright issues, please .