This is true that you have a bad design, all searchable fields should be logged in search-friendly way to make search faster.
But still, there is a way to accommodate your requirement.
Below SQL Function parse (In not so optimized way) a string for a number and if it founds it returns it as an integer.
CREATE FUNCTION dbo.fn_GetNumbers(@strInput NVARCHAR(500))
RETURNS INT
AS
BEGIN
DECLARE @strOut NVARCHAR(500) = '', @intCounter INT = 1, @OutValue INT
WHILE @intCounter <= LEN(@strInput)
BEGIN
SELECT @strOut = @strOut + CASE WHEN SUBSTRING(@strInput, @intCounter, 1) LIKE '[0-9]' THEN SUBSTRING(@strInput, @intCounter, 1) ELSE '' END
SET @intCounter = @intCounter + 1
END
IF (LEN(@strOut) > 0)
SELECT @OutValue = cast(@strOut as int)
else
SELECT @OutValue = null
RETURN @OutValue
END
Once you have that function you can use it in the below SQL to get the desired result.
SELECT GoodDescription, dbo.fn_GetNumbers(GoodDescription)
FROM
(
SELECT '3 Bleaching' as GoodDescription
UNION ALL
SELECT 'hair lotions'
UNION ALL
SELECT 'dentifrices'
UNION ALL
SELECT '9 Glasses'
UNION ALL
SELECT 'eyeglass lens'
UNION ALL
SELECT '14 Precious metals and their alloys'
UNION ALL
SELECT '18 Leather and imitations of leather'
) T
WHERE dbo.fn_GetNumbers(GoodDescription) IN (3, 18)